:- module(eplex).
:- export eplex_cleanup / 0.
:- export eplex_write / 2.
:- export eplex_read_ / 3.
:- export eplex_read / 2.
:- export eplex_add_constraints / 2.
:- export eplex_var_get_bounds / 3.
:- export eplex_var_get / 3.
:- export eplex_set / 2.
:- export eplex_get / 2.
:- export eplex_solve / 1.
:- export eplex_probe / 2.
:- export eplex_solver_setup_ / 6.
:- export eplex_solver_setup / 5.
:- export eplex_solver_setup_ / 5.
:- export eplex_solver_setup / 4.
:- export eplex_solver_setup_ / 2.
:- export eplex_solver_setup / 1.
:- export get_changeable_value / 2.
:- export suspend_on_change / 2.
:- export piecewise_linear_hull / 3.
:- export reals / 1.
:- export integers / 1.
:- export (::) / 2.
:- export $:: / 2.
:- export $=< / 2.
:- export $>= / 2.
:- export $= / 2.
:- export (=<) / 2.
:- export (>=) / 2.
:- export (=:=) / 2.
:- reexport eplex_s except add_constraint / 1, lp_eq / 3, lp_ge / 3, lp_le / 3, lp_interval / 3, lp_int_interval / 3, lp_real_interval / 3, reals / 2, integers / 2, lp_var_non_monotonic_set_bounds / 4, eplex_get / 3, eplex_cleanup / 1, eplex_probe / 3, eplex_solve / 2, eplex_var_get / 4, eplex_set / 3, eplex_read / 3, eplex_write / 3.
:- comment(summary, "Interface to external Simplex or MIP solvers").
:- comment(author, "Joachim Schimpf and Kish Shen").
:- comment(date, "$Date: 2004/10/28 17:23:51 $").
:- comment(copyright, "Parc Technologies").
:- comment(desc, html("<P>\n   This library lets you use an external Simplex or MIP solver like\n   CPLEX or XPRESS-MP from within ECLiPSe. The library provides just\n   the interface, and does not include the solver or any required licence \n   to use them.\n</P><P>\n   The is the `standalone' version of the eplex library which does not require \n   additional libraries (e.g. IC) to support the variable bounds. Instead,\n   the bounds are stored in the external solver instance. This version of\n   eplex is not completely source compatible with the other versions of eplex.\n   Note, however, that once the library is loaded, the default eplex\n   instance created is eplex and the low-level predicates are accessed\n   through the module eplex, rather than s_eplex.\n</P><P>\n    The main difference from the other eplex versions are:\n    <UL>\n    <LI>Bounds posted to a bounds keeper are not automatically seen by\n        eplex.\n    <LI>Bounds are kept by the external solver and treated as proper eplex\n        constraints. They can be posted/added to each external solver.\n        instance. New variables in the constraints will now always be added \n        to the external solver instance.\n    <LI>The bounds and integers/1 constraint does not imply any type for\n        its variables. The integers/1 constraint simply informs the external \n        solver instance to treat the variables as integer.\n    <LI>Eplex bound constraints will never cause the variable to become \n        instantiated.\n    <LI>No bounds propagation is performed with the eplex bounds\n        constraints.\n    <LI>The objective variable in a demon solver is not automatically given\n        bounds.\n    <LI>Constraints are added to the external solver instance immediately\n        after solver setup.\n </UL>\n\n</P><P>\n    The constraints provided are:\n    <DL>\n    <DT>X =:= Y</DT><DD>equality over linear expressions</DD>\n    <DT>X &gt;= Y</DT><DD>inequality over linear expressions</DD>\n    <DT>X =&lt; Y</DT><DD>inequality over linear expressions</DD>\n    <DT>X $= Y</DT><DD>equality over linear expressions</DD>\n    <DT>X $&gt;= Y</DT><DD>inequality over linear expressions</DD>\n    <DT>X $=&lt; Y</DT><DD>inequality over linear expressions</DD>\n    <DT>integers(Xs)</DT><DD>integrality of variables</DD>\n    <DT>Vs :: Bound</DT><DD>Bounds on variables</DD>\n    <DT>Vs $:: Bound</DT><DD>Bounds on variables</DD>\n    </DL>\n    Their operational behaviour is as follows:\n</P><UL>\n    <LI>When they contain no variables, they simply succeed or fail.\n\n    <LI>When they contain exactly one variable, they are translated into a\n    bound update on that variable for the external solver instance. This\n    can lead to immediate failure if the lower bound is greater than the upper.\n\n    <LI>Otherwise, the constraint is given to the external solver instance.\n    This happens either immediately, or in response\n    to certain trigger conditions.  This mechanism makes it possible to\n    tailor the solving behaviour for a particular application's needs.\n\n</UL><P>\nThe following arithmetic expression can be used inside the constraints:\n<DL>\n<DT><STRONG><B>X</B></STRONG>\n<DD>Variables. If X is not yet a ranged variable for the external solver\n    instance, it  is turned into one via an implicit declaration \n    <TT>X :: -inf..inf</TT>.\n\n<P>\n<DT><STRONG><B>123, 3.4</B></STRONG>\n<DD>Integer or floating point constants.\n\n<P>\n<DT><STRONG><B>+</B>Expr</STRONG>\n<DD>Identity.\n\n<P>\n<DT><STRONG><B>-</B>Expr</STRONG>\n<DD>Sign change.\n\n<P>\n<DT><STRONG>E1<B>+</B>E2</STRONG>\n<DD>Addition.\n\n<P>\n<DT><STRONG><B>sum</B>(ListOfExpr)</STRONG>\n<DD>Equivalent to the sum of all list elements.\n\n<P>\n<DT><STRONG>E1<B>-</B>E2</STRONG>\n<DD>Subtraction.\n\n<P>\n<DT><STRONG>E1<B>*</B>E2</STRONG>\n<DD>Multiplication.\n\n<P>\n<DT><STRONG>ListOfExpr1<B>*</B>ListOfExpr2</STRONG>\n<DD>Scalar product: The sum of the products of the corresponding\nelements in the two lists.  The lists must be of equal length.\n</DL>\n")).
:- comment($:: / 2, [amode : $::(?, ++), template : "EplexInstance: (?Vars $:: ++Lo..Hi)", args : ["Vars" : "Variable or number or a list of them", "Lo..Hi" : "Lo, Hi are numbers or arithmetic expressions"], see_also : [integers / 1, reals / 1, (::) / 2, #:: / 2, _11619 : $:: / 2], summary : "Constrains list elements to lie between the given bounds.", exceptions : [5 : "Lo..Hi is not in correct form", 5 : "Lo and Hi are of different numeric types"], desc : html("\tConstrain a variable (or all variables in a list) to take only\n\tvalues in a given range for the eplex instance EplexInstance. Any\n\tvariables that are not already problem variables for EplexInstance\n\twill be added to the problem. The range information is passed to\n\tthe external solver state associated with EplexInstance as\n\tfloats. No type information are implied by the bounds.\n\t<P>\n\tIn particular, if the bounds are given as integers, this\n\tinformation is <STRONG>not</STRONG> passed to the external solver.\n\tUnless eplex:integers/1 is invoked, any\n\tinvocation of the eplex external solver (whether via eplex_solve/1,\n\tlp_solve/2, lp_demon_setup/5 or optimize/2) will only solve a\n\tcontinuous relaxation, even when problem variables have been\n\tdeclared as integers in other solvers (e.g. ic, range, ria, fd).\n        <P>\n        No propagation is done at the ECLiPSe level with the bounds. In\n        particular, the variable is not instantiated even if the lower and\n        upper bounds are identical. The bounds may be inconsistent with the\n        bounds given for the variables in other EplexInstances or solvers\n        (i.e. this will not result in immediate failure), although failure\n        will occur if get_var_bounds/3 is called to get the generic bounds\n        of the variable.")]).
:- comment($= / 2, [template : "EplexInstance:(?X $= ?Y)", args : ["X" : "Linear expression", "Y" : "Linear expression"], see_also : [(=:=) / 2, (=<) / 2, (>=) / 2, $>= / 2, _17781 : $= / 2, $=< / 2, eplex_solver_setup / 1, eplex_solver_setup / 4, eplex_probe / 2, eplex_solve / 1, eplex_get / 2, eplex_var_get / 3, eplex_cleanup / 0], summary : "Constrains X to be equal to Y.", desc : html("\tLogically: Constrains X to be equal to Y.\n\tX and Y are linear expressions.\n\tOperationally, the constraint gets delayed until the external\n        solver state for EplexInstance is invoked.\n        </P><P>\n        The $ version of the arithmetic constraints are provided to allow \n        code to be written which does not specify the solver. They are\n        equivalent to their eplex instance counterparts without the $ prefix.\n    ")]).
:- comment($=< / 2, [template : "EplexInstance:(?X $=< ?Y)", args : ["X" : "Linear expression", "Y" : "Linear expression"], see_also : [(=:=) / 2, (=<) / 2, (>=) / 2, $>= / 2, $= / 2, _16638 : $=< / 2, eplex_solver_setup / 1, eplex_solver_setup / 4, eplex_probe / 2, eplex_solve / 1, eplex_get / 2, eplex_var_get / 3, eplex_cleanup / 0], summary : "Constrains X to be less than or equal to Y.", desc : html("\tLogically: Constrains X to be less than or equal to Y.\n\tX and Y are linear expressions.\n\tOperationally, the constraint gets delayed until the external\n        solver state for EplexInstance is invoked.\n        </P><P>\n        The $ version of the arithmetic constraints are provided to allow \n        code to be written which does not specify the solver. They are\n        equivalent to their eplex instance counterparts without the $ prefix.\n    ")]).
:- comment($>= / 2, [template : "EplexInstance:(?X $>= ?Y)", args : ["X" : "Linear expression", "Y" : "Linear expression"], see_also : [(>=) / 2, (=:=) / 2, (=<) / 2, _15476 : $>= / 2, $= / 2, $=< / 2, eplex_solver_setup / 1, eplex_solver_setup / 4, eplex_probe / 2, eplex_solve / 1, eplex_get / 2, eplex_var_get / 3, eplex_cleanup / 0], summary : "Constrains X to be greater than or equal to Y.", desc : html("\tLogically: Constrains X to be greater than or equal to Y.\n\tX and Y are linear expressions.\n\tOperationally, the constraint gets delayed until the external\n        solver state for EplexInstance is invoked.\n        </P><P>\n        The $ version of the arithmetic constraints are provided to allow \n        code to be written which does not specify the solver. They are\n        equivalent to their eplex instance counterparts without the $ prefix.\n")]).
:- comment((::) / 2, [amode : (? :: ++), template : "EplexInstance: (?Vars :: ++Lo..Hi)", args : ["Vars" : "Variable or number, or a list or submatrix of variables/numbers", "Lo..Hi" : "Lo, Hi are numbers or arithmetic expressions"], see_also : [integers / 1, reals / 1, _10915 : (::) / 2, #:: / 2, $:: / 2, get_var_bounds / 3], summary : "Constrains list elements to lie between the given bounds.", fail_if : "Lo is greater than Hi.", exceptions : [5 : "Lo..Hi is not in correct form", 5 : "Lo and Hi are of different numeric types"], desc : html("\tConstrain a variable (or all variables in a list) to take only\n\tvalues in a given range for the eplex instance EplexInstance. Any\n\tvariables that are not already problem variables for EplexInstance\n\twill be added to the problem. The range information is passed to\n\tthe external solver state associated with EplexInstance as\n\tfloats. No type information are implied by the bounds.\n\t<P>\n\tIn particular, if the bounds are given as integers, this\n\tinformation is <STRONG>not</STRONG> passed to the external solver.\n\tUnless eplex:integers/1 is invoked, any\n\tinvocation of the eplex external solver (whether via eplex_solve/1,\n\tlp_solve/2, lp_demon_setup/5 or optimize/2) will only solve a\n\tcontinuous relaxation, even when problem variables have been\n\tdeclared as integers in other solvers (e.g. ic, range, ria, fd).\n        <P>\n        No propagation is done at the ECLiPSe level with the bounds. In\n        particular, the variable is not instantiated even if the lower and\n        upper bounds are identical. The bounds may be inconsistent with the\n        bounds given for the variables in other EplexInstances or solvers\n        (i.e. this will not result in immediate failure), although failure\n        will occur if get_var_bounds/3 is called to get the generic bounds\n        of the variable.")]).
:- comment((=:=) / 2, [template : "EplexInstance:(?X =:= ?Y)", args : ["X" : "Linear expression", "Y" : "Linear expression"], see_also : [_17204 : (=:=) / 2, (=<) / 2, (>=) / 2, $>= / 2, $= / 2, $=< / 2, eplex_solver_setup / 1, eplex_solver_setup / 4, eplex_probe / 2, eplex_solve / 1, eplex_get / 2, eplex_var_get / 3, eplex_cleanup / 0], summary : "Constrains X to be equal to Y.", desc : html("\tLogically: Constrains X to be equal to Y.\n\tX and Y are linear expressions.\n\tOperationally, the constraint gets delayed until the external\n        solver state for EplexInstance is invoked.")]).
:- comment((=<) / 2, [template : "EplexInstance:(?X =< ?Y)", args : ["X" : "Linear expression", "Y" : "Linear expression"], see_also : [(=:=) / 2, _16057 : (=<) / 2, (>=) / 2, $>= / 2, $= / 2, $=< / 2, eplex_solver_setup / 1, eplex_solver_setup / 4, eplex_probe / 2, eplex_solve / 1, eplex_get / 2, eplex_var_get / 3, eplex_cleanup / 0], summary : "Constrains X to be less than or equal to Y.", desc : html("\tLogically: Constrains X to be less than or equal to Y.\n\tX and Y are linear expressions.\n\tOperationally, the constraint gets delayed until the external\n        solver state for EplexInstance is invoked.")]).
:- comment((>=) / 2, [template : "EplexInstance:(?X >= ?Y)", args : ["X" : "Linear expression", "Y" : "Linear expression"], see_also : [_14900 : (>=) / 2, (=:=) / 2, (=<) / 2, $>= / 2, $= / 2, $=< / 2, eplex_solver_setup / 1, eplex_solver_setup / 4, eplex_probe / 2, eplex_solve / 1, eplex_get / 2, eplex_var_get / 3, eplex_cleanup / 0], summary : "Constrains X to be greater than or equal to Y.", desc : html("\tLogically: Constrains X to be greater than or equal to Y.\n\tX and Y are linear expressions.\n\tOperationally, the constraint gets delayed until the external\n        solver state for EplexInstance is invoked.")]).
:- comment(eplex_add_constraints / 2, [template : "EplexInstance: eplex_add_constraints(+Constraints,+Integers)", args : ["Constraints" : "A (possibly empty) list of equality or inequality constraints", "Integers" : "A (possibly empty) list of variables to be considered as integers"], see_also : [lp_add_constraints / 3, lp_demon_setup / 5, lp_add / 3, lp_add_constraints / 4, $= / 2, $=< / 2, $>= / 2, (=:=) / 2, (=<) / 2, (>=) / 2], resat : no, fail_if : "Any ground (no variable) or bound constraints (one variable) is self-inconsistent.", exceptions : [4 : "Constraints or Integers uninstantiated.", 5 : "Some constraint in Constraints is non-linear."], summary : "Add new constraints to the eplex instance EplexInstance, possibly triggering it.", desc : html("<P>\n  Add new constraints (with possibly new variables) to the eplex instance\n  EplexInstance.  Cstrs is a list of equality or inequality constraints; \n  NewIntegers is a list of (possibly new) variables that should be\n  consider as integers  This is logically the same as posting the\n  constraints one by one to the solver, but it may be more convienient if \n  the constraints are already collected as a list.\n</P><P>\n  Operationally, if a solver state has been associated with the eplex\n  instance, the constraints are added to the solver state in one go. \n  For some solvers, this can be more efficient than adding the constraints\n  incrementally. \n</P><P>\n  If the new_constraint trigger option was selected, then the solver will\n  be invoked after the adding of the constraints.  The constraints will be\n  removed on backtracking.\n</P><P>\n  The constraints are normalised and simplified before being passed to\n  the external solver. If any constraint is ground, they are tested for\n  consistency.\n</P><P>\n  Note that variables in NewIntegers can be any problem variables. In\n  previous versions of ECLiPSe, there was a restriction that the variables\n  be new problem variables; this restriction has been removed.\n</P><P>\n\n </P>")]).
:- comment(eplex_cleanup / 0, [template : "EplexInstance:eplex_cleanup", summary : "Destroy the external solver associated with EplexInstance.", desc : html("<P>\n    Destroy the specified solver, free all memory, etc.  Note that ECLiPSe\n    will normally do the cleanup automatically, for instance when execution\n    fails across the solver setup. The solver is disassociated with \n    EplexInstance, and any outstanding constraints not yet collected by the\n    solver are removed, with a warning to the user. In effect, EplexInstance\n    is reinitialised and can now be associated with a new solver without\n    backtracking. Note that this last behaviour is unlike lp_cleanup/1, which\n    also destroy the solver and disassociate it from the eplex instance (if \n    any), but does not remove any outstanding constraints.\n\n</P>")]).
:- comment(eplex_get / 2, [template : "EplexInstance:eplex_get(++ParamName, -Value)", args : ["ParamName" : "Name of parameter (atom)", "Value" : "Returned value for ParamName"], summary : "Retrieve information about solver state and results for eplex instance EplexInstance.", exceptions : [5 : "EplexInstance does not a solver setup for it."], see_also : [eplex_solver_setup / 4, eplex_set / 2, lp_set / 3, lp_get / 3, lp_add_constraints / 4], desc : html("<P>\n   Retrieve information about solver state and results for the eplex instance\n   <TT>EplexInstance</TT>. <TT>ParamName</TT> is the same as that\n   for lp_get/3, which retrieves the same information via the solver state.\n</P>\n\n<DL>\n<P>  \n     <DT><STRONG><TT>vars</TT></STRONG>\n     <DD>Returns a term ''(X1,...,Xn) whose arity is the number of\n         variables involved in the solver's constraint set, and whose\n         arguments are these variables.\n\n<P>\n     <DT><STRONG><TT>ints</TT></STRONG>\n     <DD>Returns a list [Xi1,...,Xik] which is the subset of the problem\n         variables that the solver considers to be integers.\n\n<P>\n     <DT><STRONG><TT>constraints_norm</TT></STRONG>\n     <DD>Returns a list of the problem constraints in normalised form.\n         They may be simplified with respect to the original set that \n         was passed to lp_setup/4.\n\n<P>\n     <DT><STRONG><TT>constraints</TT></STRONG>\n     <DD>Returns a list of the problem constraints in denormalised (readable)\n         form.  They may be simplified with respect to the original set\n         that was passed to lp_setup/4.\n\n<P>\n     <DT><STRONG><TT>objective</TT></STRONG>\n     <DD>Returns a term min(E) or max(E), representing objective function\n         and optimisation direction. E is a linear expression: any\n         quadratic components will not be retrieved.\n\n<P>\n     <DT><STRONG><TT>num_cols</TT></STRONG>\n     <DD>Returns the number of columns (i.e. variables) in the matrix of the\n     solver state.\n\n<P>\n     <DT><STRONG><TT>num_rows</TT></STRONG>\n     <DD>Returns the number of rows (i.e. constraints) in the matrix of the\n     solver state.\n\n<P>\n     <DT><STRONG><TT>num_nonzeros</TT></STRONG>\n     <DD>Returns the number of non-zero coefficients in the matrix of the\n     solver state.\n\n<P>\n     <DT><STRONG><TT>num_ints</TT></STRONG>\n     <DD>Returns the number of columns (i.e. variables) constrained to be\n     integers in the matrix of the solver state.\n\n<P>\n     <DT><STRONG><TT>num_quads</TT></STRONG>\n     <DD>Returns the number of non-zero coefficients in the quadratic\n     coefficient matrix (Q-matrix) of the solver state.\n\n<P>\n     <DT><STRONG><TT>method</TT></STRONG>\n     <DD>Returns the method that is specified to solve the problem. If an\n     auxiliary  method can be given for the method, and this auxiliary\n     method is not <TT>default</TT>, the method will be returned as \n     Method(Aux), e.g. <TT>barrier(none)</TT>. The method will be \n     <TT>default</TT> unless otherwise specified by the the user (at setup or \n     via eplex_setup/2 or lp_setup/3).\n     In case of MIP solving, this is the start algorithm (the one that \n     is used to solve the initial relaxation).\n\n<P>\n     <DT><STRONG><TT>node_method</TT></STRONG>\n     <DD>Applicable to MIP problems only. Returns the method that is\n     specified to solve the problem at the nodes of the branch-and-bound\n     tree. If an auxiliary method can be given for the method, and this\n     auxiliary method is not <TT>default</TT>, the method will be returned\n     as Method(Aux), e.g. <TT>barrier(none)</TT>. The method will be\n     <TT>default</TT> unless otherwise specified by the the user (at setup\n     or via eplex_setup/2 or lp_setup/3).\n     Note that the method for solving the root (initial relaxation) node\n     is specified by <TT>method</TT>.\n\n<P>\n     <DT><STRONG><TT>status</TT></STRONG>\n     <DD>Status that was returned by the most recent invocation of the \n         external solver.\n\n<P>\n     <DT><STRONG><TT>cost</TT></STRONG>\n     <DD>Objective value (i.e. cost/profit) of the current solution.\n         Fails if no solution has been computed yet.\n\n<P>\n     <DT><STRONG><TT>typed_solution</TT></STRONG>\n     <DD>Returns a term ''(X1,...,Xn) whose arguments are the properly\n         typed (integer or float) solution values for the corresponding\n         problem variables (<TT>vars</TT>).  The floating point solutions\n         are the same as returned by <TT>solution</TT>, the integers are\n         obtained by rounding the corresponding floating-point solution to\n         the nearest integer.  To instantiate the problem variables to\n         their solutions, unify this term with the corresponding term\n         containing the variables:\n         Fails if no solution has been computed yet.\n\n<PRE>\n    instantiate_solution(Handle) :-\n        lp_get(Handle, vars, Vars),\n        lp_get(Handle, typed_solution, Values),\n        Vars = Values.\n</PRE>\n\n<P>\n    <DT><STRONG><TT>slack</TT></STRONG>\n    <DD>Returns a list of floating-point values representing the constraint\n        slacks. The order corresponds to the list order in\n        <TT>constraints</TT>. Fails if no solution has been computed yet,\n        or if the slack option was not set to yes.\n\n<P>\n    <DT><STRONG><TT>slack(Indexes)</TT></STRONG>\n    <DD>Returns a list of floating-point values representing the slack\n        values for the constraints represented by Indexes. Indexes are \n        a list of constraint indecies (as returned by lp_add_constraints/4),\n        and the order of the returned list corresponds to the order in\n        <TT>Indexes</TT>.  Fails if no solution has been computed yet,\n        or if the slack option was not set to yes.\n\n<P>\n    <DT><STRONG><TT>dual_solution</TT></STRONG>\n    <DD>Returns a list of floating-point values representing the dual\n        solutions.  The order corresponds to the list order in\n        <TT>constraints</TT>.  Fails if no solution has been computed yet,\n        or if the dual_solution option was not set to yes.\n\n<P>\n    <DT><STRONG><TT>dual_solution(Indexes)</TT></STRONG>\n    <DD>Returns a list of floating-point values representing the dual\n        solutions for the constraints represented by Indexes. Indexes are\n        a list of constraint indecies (as returned by lp_add_constraints/4),\n        and the order of the returned list  corresponds to the order in\n        <TT>Indexes</TT>.  Fails if no solution has been computed yet,\n        or if the dual_solution option was not set to yes.\n\n<P>\n    <DT><STRONG><TT>demon_tolerance</TT></STRONG>\n    <DD>Returns a comma-separated pair <TT>(RealTol,IntTol)</TT> of\n        floating-point values which specify how far outside a variable's\n        range an lp-solution can fall before lp_demon_setup/5\n        re-triggers. The tolerances differ for real (default 0.00001) and\n        integer (default 0.5) variables.\n\n<P>\n    <DT><STRONG><TT>simplex_iterations</TT></STRONG>\n    <DD>Returns the external solver's count of simplex iterations.\n\n<P>\n    <DT><STRONG><TT>node_count</TT></STRONG>\n    <DD>Returns the external MIP solver's node count. Note that this may \n        or may not include the initial root node.\n<P>\n    <DT><STRONG><TT>statistics</TT></STRONG>\n    <DD>Returns a list of counter values <TT>[Successes, Failures,\n        Aborts]</TT>, indicating how often lp_solve/2 was invoked on the\n        Handle, and how many invocations succeeded, failed and aborted\n        respectively.\n\n<P>\n    <DT><TT>timeout</TT></STRONG>\n    <DD>Returns the time-out value for the solver state. This is the amount\n        of CPU time in seconds that the external solver will be allow to\n        spend solving the problem before timing out. The value is 0 if \n        no time-out has been set.\n<P>\n     <DT><STRONG><TT>optimizer_param(Param)</TT></STRONG>\n     <DD>Returns the value of the external solver's parameter Param\n         for the problem represented by Handle. The external solver \n         has a number of parameters that affect the way they work, and \n         this queries their values. If Param is not a valid parameter for\n         the solver, an out of range exception is raised. See below for \n         more details on the parameters.\n<P>\n    <DT><STRONG><TT>post_equality_when_unified</TT></STRONG>\n    <DD>Returns the value (yes or no) if an equality constraint will be\n        posted to a solver if two variables in the solver's problem are \n        unified. \n<P>\n    <DT><STRONG><TT>pool</TT></STRONG>\n    <DD>Returns the name of the eplex instance (if any) associated with \n        the solver state. Fails otherwise. Only useful if called with \n        lp_get/3.\n<P>\n    <DT><STRONG><TT>handle</TT></STRONG>\n    <DD>Returns the solver state handle (if any) associated with the eplex \n        instance. Fails otherwise. Only useful if called with eplex_get/2.\n<P>\n</DL>\nNote that reduced_cost, slack, dual_solution can only be retrieved\nwhen previously requested in the option list of lp_setup/4 or with lp_set/3.\n\n<P>\nFor the external solver's control parameter specified by\noptimizer_param(Param), Param must be an atom. The Value returned is\neither an integer, float or atom, depending on the parameter. The parameter\nis generally specific to a solver and version, and also, they may be\nproblem specific, or global, again depending on the solver version. In all\ncases, the value returned by lp_get/3 is the current value for the parameter\nfor the problem Handle. Refer to the solver documentation for details on the \nparameters. The names of the parameters are derived from the names of the \nparameters in the external solver. For CPLEX, take the parameter name from the CPLEX manual (or cplex.h), remove the CPX_PARAM_ prefix and convert the \nrest to lower case, e.g.\n\n<PRE>\n        CPX_PARAM_NODELIM becomes nodelim. \n</PRE>\nFor XPRESS-MP (version 13 and newer), take the parameter name from the \nmanual (or xpresso.h), remove the XPRS_ prefix (if present) and convert \nthe rest to lower case, e.g.\n<PRE>\n\tMAXNODE or XPRS_MAXNODE becomes maxnode. \n</PRE>\n    (pre version 13, the parameter names are prefixed by N_ instead of XPRS_).\n\n<P>\n    The following parameter names are additional aliases that work for\n    either solver:\n<DL>\n    <DT><TT>crash</TT>\n\t<DD>CPX_PARAM_CRAIND (CPLEX) or XPRS_CRASH (XPRESS-MP) -integer\n    <DT><TT>feasibility_tol</TT>\n\t<DD>CPX_PARAM_EPRHS (CPLEX) or XPRS_FEASTOL (XPRESS-MP) - float\n    <DT><TT>integrality</TT>\n\t<DD>CPX_PARAM_EPINT (CPLEX) or XPRS_MIPTOL (XPRESS-MP) - float\n    <DT><TT>iteration_limit</TT>\n\t<DD>CPX_PARAM_ITLIM (CPLEX) or XPRS_LPITERLIMIT (XPRESS-MP) -integer\n    <DT><TT>node_limit</TT>\n\t<DD>CPX_PARAM_NODELIM (CPLEX) or XPRS_MAXNODE (XPRESS-MP) -integer\n    <DT><TT>objdifference</TT>\n\t<DD>CPX_PARAM_OBJDIF (CPLEX) or XPRS_MIPADDCUTOFF (XPRESS-MP) - float\n    <DT><TT>refactor</TT>\n\t<DD>CPX_PARAM_REINV (CPLEX) or XPRS_INVERTFREQ (XPRESS-MP) -integer\n    <DT><TT>scrind</TT>\n\t<DD>CPX_PARAM_SCRIND (CPLEX) or XPRS_OUTPUTLOG (XPRESS-MP) -integer\n</DL>\n\n            ")]).
:- comment(eplex_instance / 1, [amode : eplex_instance(++), args : ["EplexInstance" : "Eplex instance name (atom)"], summary : "Initialises the eplex instance EplexInstance.", desc : html("  <P>\n  Initialises the eplex instance EplexInstance. An eplex instance is an\n  instance of the eplex solver, to which eplex linear arithmetic and \n  integrality constraints can be posted, and to which an external LP/MIP\n  solver can be associated and used to optimise the posted constraints\n  with respect to some objective. \n  </P><P>\n  If EplexInstance is not an already existing eplex instance, a new eplex\n  instance will be created and initialised. If it is an existing eplex\n  instance, and it is not currently being used (having no outstanding posted\n  constraints and no associated solver), it is effectively reinitialised.\n  Otherwise, the predicate aborts with an error. Note that an eplex instance\n  is a module, and each eplex instance can be associated with at most one\n  solver at any time and vice versa. An eplex instance should NOT be\n  erased (e.g. using erase_module/1), as this would only erase the module,\n  but not the information that eplex keeps on it as an eplex instance.\n  </P>\n  "), see_also : [$= / 2, $=< / 2, $>= / 2, (=:=) / 2, (=<) / 2, (>=) / 2, $:: / 2, (::) / 2, integers / 1, reals / 1, eplex_solver_setup / 1, eplex_solver_setup / 4, eplex_probe / 2, eplex_solve / 1, eplex_get / 2, eplex_var_get / 3, eplex_cleanup / 0]]).
:- comment(eplex_probe / 2, [template : "EplexInstance:eplex_probe(+Probes, -Cost)", args : ["Probes" : "Temporary probe specification(s)", "Cost" : "Value of solution"], summary : "Invoke EplexInstance's external solver, probing the problem temporary modified by the probe specifications.", see_also : [eplex_solve / 1, eplex_solver_setup / 1, eplex_solver_setup / 4, eplex_get / 2, eplex_var_get / 3, eplex_set / 2], desc : html("<P>\n   Similar to eplex_solve/1, but the problem is first temporarily modified\n   as specified in Probes. Probes is a list of one or more probe\n   specification that specifies how the problem is modified. After the call\n   to this predicate, the problem is restored for the external\n   solver. However, the result from the probe (obtainable from\n   eplex_var_get/3 and eplex_get/2) are retained.\n</P><P>\n   The following probe specifcations are allowed:\n<DL>\n    <DT>min(Expr)/max(Expr)<DD>\n        Minimise/maximise the problem with the objective function Expr.\n        Only existing problem variables can be given in Expr. Cannot be\n        used in conjunction with objsense or objexpr.\n    <DT>objsense(Sense)<DD>\n        Sense is either min or max. Solves the problem with the original\n        objective function, but with the sense given in Sense rather than\n        that specified at setup. If only the sense of the objective is to \n        be changed, this changes the objective more efficiently than using\n        min(Expr)/max(Expr). Cannot be used in conjunction with min/max or\n        objexpr.\n    <DT>objexpr(Expr)<DD>\n        Optimise the problem with respect to the objective function Expr,\n        without changing the optimisation direction specified at problem\n        setup. Cannot be used in conjunction with objsense or min/max.\n    <DT>fixed<DD>\n        The problem is solved as an LP problem by `fixing' the integer\n        variables to their optimal MIP solution values. If there is an\n        existing MIP solution for the problem, eplex will try to use that;\n        otherwise, the problem is first solved as a MIP problem\n        first. `Fixed' probing is useful for providing reduced costs for\n        MIP problems. Note that reduced costs for the variables are only be\n        available if the reduced_cost option is set to yes for the problem\n        (this can be done either at problem setup, or by using\n        eplex_set/2). For a problem without integer variables, the original\n        problem is solved without change.  Note that this probe\n        specification is not available if the mip_use_copy option is set to\n        no for external solvers that cannot modify a MIP problem.  Cannot\n        be used in conjunction with `relaxed'.\n    <DT>relaxed<DD>\n        The problem is solved as an LP problem by relaxing all the integer\n        constraints.  For a problem with integer variables, this should be\n        equivalent to the initial relaxation solved at the start of the MIP\n        search. Depending on the solver, the discreteness of the integer\n        variables may still be taken into account during presolve. To\n        ensure that the problem solved is exactly the LP problem without\n        any integer constraints, presolve should be off. For a problem\n        without integer variables, the original problem is solved without\n        change. Note that this probe specification is not available if the\n        mip_use_copy option is set to no for external solvers that cannot\n        modify a MIP problem. Cannot be used in conjunction with `fixed'.\n\n</DL>\n</P>"), fail_if : "External solver was unable to find a solution.", exceptions : [5 : "EplexInstance does not a solver setup for it.", eplex_suboptimal : "Solution was found, but is possibly suboptimal", eplex_unbounded : "Problem is unbounded, no solution values", eplex_unknown : "Result is unknown (infeasible or unbounded)", eplex_abort : "External solver aborted for some reason", 6 : "mip_use_copy option was set to no (solver dependent) for probes that require yes."]]).
:- comment(eplex_read / 2, [template : "EplexInstance:eplex_read(++Format,++File)", args : ["Format" : "lp or mps", "File" : "File name"], see_also : [eplex_write / 2, lp_write / 3, lp_setup / 4, eplex_probe / 2], summary : "Read a problem from a file into eplex instance EplexInstance.", exceptions : [5 : "EplexInstance already has a solver setup for it."], desc : html("\n   Read a problem from a file and setup a solver for it in EplexInstance.\n   A solver should not already be setup for EplexInstance. Format is lp or\n   mps. Note that minimisation of the objective is assumed for mps format,\n   as the sense of the objective is not included in the mps format.\n   Minimisation is also assumed for external solvers that ignore the\n   optimisation direction of the lp file (e.g. Xpress).  Note also that\n   although quadratic problems can be read in correctly if supported by the\n   external solver, the quadratic objective coefficients are not extracted\n   from the problem by eplex. These coefficients are used to set/reset the\n   objective when a problem is probed with a different objective in\n   eplex_probe/2 or lp_probe/3, so the objective will not be changed or\n   restored correctly in this case.  \n")]).
:- comment(eplex_set / 2, [template : "EplexInstance:eplex_set(++ParamName, -Value)", args : ["ParamName" : "Name of parameter (atom)", "Value" : "New value for ParamName"], resat : no, summary : "Change initial options for solver state associated with EplexInstance", exceptions : [5 : "EplexInstance does not a solver setup for it."], see_also : [eplex_solver_setup / 4, eplex_set / 2, lp_set / 3, lp_get / 3], desc : html("<P>\nThis primitive can be used to change some of the initial options\neven after setup of a solver for eplex instance <EM>EplexInstance</EM>.\n<EM>What</EM> can be one of the following:\n\n<DL>\n    <DT><STRONG><TT>method</TT></STRONG>\n        <DD>Set the method that will be used to solve the problem.  Value\n        is one of <TT>default, primal, dual, net, net(Simplex), barrier,\n        barrier(Crossover), sifting, sifting(SubMethod)</TT>. Simplex can\n        be one of <TT>default, primal, dual</TT>, specifying the Simplex\n        method to use in the Network Simplex algorithm. Crossover can be\n        one of <TT>default, primal, dual, none</TT>, specifying the\n        crossover method to use for the barrier method. SubMethod could be\n        one of default, primal, dual, net, barrier</TT>, specifying the\n        method to use for the subproblems in the sifting method. Note that\n        some of these methods may not be available on all external solvers.\n        In case of MIP solving, this is the start algorithm (the one that\n        is used to solve the initial relaxation). \n\n<P>\n    <DT><STRONG><TT>node_method</TT></STRONG>\n        <DD>Applicable to MIP problems only. Set the method that will be\n        used to solve the problem at the nodes (except the root) of the \n        branch-and-bound tree. Note that the method for solving the root\n        node is controlled by the <TT>method</TT> option. Value can be set\n        to the same values as in the <TT>method</TT> option, although \n        there may be more restrictions on what the actual methods/auxiliary\n        methods that are allowed in combination with the root method,\n        due to limitations/restrictions from the external solver. A warning\n        will be given when the problem is solveed if this is the case, and \n        the default method used instead.\n\n<P>\n    <DT><STRONG><TT>solution</TT></STRONG>\n        <DD>Make the solutions available each time the problem has been\n        (re-)solved successfully.\n        Value is one of the atoms <TT>yes</TT> or <TT>no</TT>.\n\n<P>\n    <DT><STRONG><TT>reduced_cost</TT></STRONG>\n        <DD>Make the reduced costs available each time the problem has been\n        (re-)solved successfully. If the problem is a MIP, then depending on\n        the external solver, this is either unavailable or are the values\n        for the optimal LP node. \n        Value is one of the atoms <TT>yes</TT> or <TT>no</TT>.\n\n<P>\n    <DT><STRONG><TT>slack</TT></STRONG>\n        <DD>Make the constraint slacks available each time the problem has been\n        (re-)solved successfully.\n        Value is one of the atoms <TT>yes</TT> or <TT>no</TT>.\n\n<P>\n    <DT><STRONG><TT>dual_solution</TT></STRONG>\n        <DD>Make the dual solutions available each time the problem has been\n        (re-)solved successfully. If the problem is a MIP, then depending on\n        the external solver, this is either unavailable or are the values\n        for the optimal LP node. \n        Value is one of the atoms <TT>yes</TT> or <TT>no</TT>.\n\n<P>\n    <DT><STRONG><TT>keep_basis</TT></STRONG>\n        <DD>Store the basis each time the problem has been solved successfully,\n        and use this basis as a starting point for re-solving next time.\n        Value is one of the atoms <TT>yes</TT> or <TT>no</TT>.\n\n<P>\n    <DT><STRONG><TT>demon_tolerance</TT></STRONG>\n        <DD>Specify how far outside a variable's range an lp-solution\n        can fall before lp_demon_setup/5 re-triggers.\n        Value is a comma-separated pair <TT>(RealTol,IntTol)</TT> of \n        floating-point values (default <TT>(0.00001,0.5)</TT>).\n\n<P>\n    <DT><STRONG><TT>use_var_names</TT></STRONG>\n        <DD>Specify if variable names (set using <TT>set_var_name/2</TT> of the\n        var_name library) should be passed to the external solver. If a\n        particular variable does not have a name, a solver's default name\n        would be used. Note that for XPRESS-MP, there is a limit on the\n        length of the name, which can be changed between 8 and 64 in steps\n        of 8 with the parameter <TT>N_NAMLEN</TT>. Variable names longer\n        than this limit are truncated to the limit. Note also that only \n        new variables from constraints added after the <TT>lp_set/3</TT> call \n        will pass their names to the external solver.\n        Value is one of the atoms <TT>yes</TT> or <TT>no</TT>.\n<P>\n    <DT><STRONG><TT>timeout</TT></STRONG>\n        <DD>Set the external solver to time-out after <TT>Value</TT>\n        seconds.  The solver will abort (in either the abort or suboptimal\n        state, depending on if a suboptimal solution was found) if the\n        optimal solution was not found within the time limit. In cases\n        where the solver expects an integer for the time-out interval, the\n        time given is rounded up to the next integer value. This should be\n        used instead of the solver specific optimizer_param(Param) for\n        setting timeouts.\n        Value is a positive number.\n<P>\n<DT><STRONG><TT>suboptimal_handler</TT></STRONG>\n        <DD>Value is a user defined goal to handle the case when the\n        external solver returned a suboptimal solution (because the problem\n        was aborted). Value would replace any existing suboptimal handler,\n        and would also be run in place of raising the default\n        <TT>eplex_suboptimal</TT> event.\n<P>\n<DT><STRONG><TT>unbounded_handler</TT></STRONG>\n        <DD>Value is a user defined goal to handle the case when the\n        problem is unbounded. Value would replace any existing unbounded\n        handler, and would be run in place of raising the default\n        <TT>eplex_unbounded</TT> event.\n<P>\n<DT><STRONG><TT>unknown_handler</TT></STRONG>\n        <DD>Value is a user defined goal to handle the case when the\n        external solver was not able to determine if the problem is\n        unbounded Value would replace any existing unknown handler, and\n        would be run in place of raising the default <TT>eplex_unknown</TT>\n        event.\n<P>\n<DT><STRONG><TT>abort_handler</TT></STRONG>\n        <DD>Value is a user defined goal to handle the case when the\n        external solver aborted without finding any solution.  Value would\n        replace any existing abort handler, and would be run in place of\n        raising the default <TT>eplex_abort</TT> event.\n<P>\n    <DT><STRONG><TT>optimizer_param(Param)</TT></STRONG>\n        <DD>Set the external solver's control parameter Param for the problem\n        <TT>Handle</TT>. If the solver's parameters are global and not\n        problem specific, an unimplemented functionality exception would\n        be raised. See lp_get/3 for more details on the external solver's\n        parameters. Note that the new setting is <EM>not</EM> undone on \n        backtracking.\n<P>\n    <DT><STRONG><TT>write_before_solve</TT></STRONG>\n       <DD>Value can be the pair (Format,File) or the atom no. If\n       (Format,File) is given, Eplex will ask the external solver to dump\n       the problem each time the solver is invoked by calling\n       <TT>lp_write/3</TT>. This allows the problem in an\n       <TT>eplex_probe/2</TT> or <TT>lp_probe/3</TT> to be\n       dumped. <TT>Format</TT> and <TT>File</TT> are simply passed to\n       <TT>lp_write/3</TT>. `no' will turn off this dumping.\n<P>\n    <DT><STRONG><TT>post_equality_when_unified</TT></STRONG>\n        <DD>Value can be the atoms yes or no. Determines if an equlity\n        constraint will be posted to a solver when two of its variables are\n        unified. Setting Value to no means that the constraint will not be\n        posted. Note that this could mean that the\n        solver's problem may become inconsistent with ECLiPSe's. \n<P>\n</DL>\n  Making solutions available means that they can be retrieved using\n  lp_get/3 or lp_var_get/4 after the solver has been run successfully.\n</P>")]).
:- comment(eplex_solve / 1, [template : "EplexInstance:eplex_solve(-Cost)", args : ["Cost" : "Value of returned solution"], summary : "Explicitly invoke the external solver associated with EplexInstance.", fail_if : "External solver was unable to find a solution.", see_also : [eplex_solver_setup / 4, eplex_solver_setup / 1, eplex_var_get / 3, eplex_get / 2, $= / 2, $=< / 2, $>= / 2, (=:=) / 2, (>=) / 2, (=<) / 2, $:: / 2, (::) / 2, integers / 1, reals / 1], desc : html("<P>\n   Explicitly triggers the solver associated with the eplex instance \n   EplexInstance. If the solver was set up without any trigger conditions,\n   then it needs to be explicitly triggered via a call to this predicate.\n</P><P>\n   The external solver's LP, QP or MIP solver is applied to the\n   problem represented by the eplex instance.  Precisely which method is used\n   depends on the options given at set up.  eplex_solve/1 fails if\n   there is no solution or succeeds if an optimal solution is found,\n   returning the solution's cost in Cost. After a success, various\n   solution and status information can be retrieved using eplex_get/2\n   and eplex_var_get/3.\n</P><P>\n   When a solver is triggered repeatedly, each invocation will\n   automatically take into account the current variable bounds.  The set of\n   constraints considered by the solver is the one given when the solver\n   was created plus any new constraints that were posted in the\n   meantime.\n</P><P>\n   The user can define their own handlers (per eplex instance/problem) to\n   handle cases where there was some  error condition, or some limits were \n   exceeded during the solving of the problem. If no handler was defined,\n   by default an event would be raised. These are:\n<DL>\n    <DT>suboptimal handler (eplex_suboptimal event)<DD>\n    \tThis means that a solution was found but it may be suboptimal.\n\tThe default behaviour is to print a warning and succeed.\n    <DT>unbounded_handler (eplex_unbounded event)<DD>\n\tThis means that the problem is unbounded.  The default\n\tbehaviour is to bind Cost to infinity (positive or negative\n\tdepending on the optimisation direction), print a warning and\n\tsucceed.  CAUTION: No solution values are computed when the\n\tproblem is unbounded, so unless the problem was set up with\n\tthe solution(no) option, an error will occur when trying to\n\tcontinue as if the optimisation had succeeded.\n    <DT>unknown_handler (eplex_unknown event)<DD>\n    \tThis means that due to the solution method chosen, it is unknown\n\twhether the problem is unbounded or infeasible. The default\n\tbehaviour is to print a warning and fail (even though this\n\tmay be logically wrong!).\n    <DT>abort_handler (eplex_abort event)<DD>\n    \tSome other error condition occurred during optimisation.\n\tThe default behaviour is to print an error and abort.\n</DL>\n</P><P>\n   Note that the events are raised for the low-level primitive lp_solve/2,\n   which is called by eplex_solve/1.\n</P>"), exceptions : [5 : "EplexInstance does not a solver setup for it.", eplex_suboptimal : "Solution was found, but is possibly suboptimal", eplex_unbounded : "Problem is unbounded, no solution values", eplex_unknown : "Result is unknown (infeasible or unbounded)", eplex_abort : "External solver aborted for some reason"]]).
:- comment(eplex_solver_setup / 1, [template : "EplexInstance:eplex_solver_setup(+Objective)", args : ["Objective" : "Objective function: min(CostExpr) or max(CostExpr)"], summary : "Setup an external solver state for eplex instance EplexInstance", see_also : [$= / 2, $=< / 2, $>= / 2, (=:=) / 2, (>=) / 2, (=<) / 2, $:: / 2, (::) / 2, integers / 1, reals / 1, eplex_solver_setup / 4, eplex_probe / 2, eplex_solve / 1, eplex_get / 2, eplex_var_get / 3], desc : html("<P>\n  Setup a new external solver state for the eplex instance EplexInstance. \n  The solver state will be associated with EplexInstance;\n  EplexInstance must not already have a solver state associated with it.\n  Once the solver state is setup, it can be invoked (e.g. via eplex_solve/1 \n  or eplex_probe/2) to optimise the Objective function. \n</P><P>\n    CostExpr is a linear expression\n    (or quadratic if supported by the external solver).\n</P><P>\n  Declaratively, this can be seen as a compound constraint representing all\n  the individual linear constraints that have been set so far and are going\n  to be set up later for <TT>EplexInstance</TT>. The invoking of this \n  constraint is done explicitly by the user, usually via eplex_solve/1.\n  Operationally, when the external solver is invoked, the delayed \n  constraints posted to <TT>EplexInstance</TT> are collected and taken into\n  account.\n</P><P>\n  This is a simplified version of eplex_solver_setup/4, it is equivalent to\n  calling eplex_solver_setup/4 with the following defaults:\n<PRE>\n       eplex_solver_setup(Objective, _, [], 0, [])\n</PRE>\n")]).
:- comment(eplex_solver_setup / 4, [template : "EplexInstance:eplex_solver_setup(+Objective, ?Cost, ++ListOfOptions, +TriggerModes)", args : ["Objective" : "Objective function: min(CostExpr) or max(CostExpr)", "Cost" : "Variable bounded by the optimal solution", "ListOfOptions" : "List of solver options", "TriggerModes" : "List of conditions for re-triggering solver"], summary : "Setup an external solver state for eplex instance EplexInstance", see_also : [$= / 2, $=< / 2, $>= / 2, (=:=) / 2, (>=) / 2, (=<) / 2, $:: / 2, (::) / 2, integers / 1, reals / 1, eplex_solver_setup / 1, eplex_probe / 2, eplex_solve / 1, eplex_get / 2, eplex_var_get / 3, lp_demon_setup / 5, lp_setup / 4], desc : html("<P>\n  Setup a new external solver state for the eplex instance EplexInstance. \n  The solver state will be associated with EplexInstance;\n  EplexInstance must not already have a solver state associated with it.\n  This predicate allow various options to be specified when setting up the\n  solver state. <TT>ListOfOptions</TT> allows a list of solver options to \n  be specified, and <TT>TriggerModes</TT> allows the \n  solver state to be set up as a demon so that the external solver is \n  automatically invoked when the conditions for re-triggering specified in\n  <TT>TriggerModes</TT> are met. The external solver can also be invoked \n  explicitly via eplex_solve/1. \n</P><P>\n  Declaratively, this can be seen as a compound constraint representing all\n  the individual linear constraints that have been set so far and are going\n  to be set up later for <TT>EplexInstance</TT>. Operationally, when the\n  external solver is invoked, the delayed constraints posted to \n  <TT>EplexInstance</TT> are collected and taken into account.\n</P><P>\n  <TT>CostExpr</TT> is a linear cost expression (or quadratic, if supported\n  by the external solver).\n</P><P>\n  If the solution is optimal, the external solver's objective solution\n  will be exported as a bound for <TT>Cost</TT>: For a minimization\n  problem, each solution's cost becomes a lower bound, for maximization an\n  upper bound on Cost.  This technique allows for repeated re-solving with\n  reduced bounds or added constraints. Note that Cost is not automatically \n  made a problem variable (it can be a problem variable if there are\n  constraints that  involve it), and thus may not have bounds associated\n  with in. In order for the bounds information not to be lost, some bounds\n  should be given to <TT>Cost</TT> (e.g. making it a problem variable (but\n  this might introduce unecessarly self-waking on bounds change), or via\n  another solver with bounds (e.g. ic)). \n</P><P>\n  <TT>ListOfOptions</TT> is the same as in the low-level primitive \n  lp_demon_setup/5, except that EplexInstance is implicitly associated with\n  the new external solver state, so the <TT>collect_from</TT> option of\n  lp_demon_setup/5 is not allowed (it is set to <TT>\n  collect_from(pool(EplexInstance))</TT> by the predicate). See \n  below for more details.\n</P><P>\n  <TT>TriggerModes</TT> specifies under which conditions the external solver\n  will be re-triggered. If no condition is specified, then the solver must\n  be explicitly triggered, usually via eplex_solve/1. The conditions are the\n  same as in the low-level primitive lp_demon_setup/5 called by this predicate.\n  See below (after <TT>ListOfOptions</TT> descriptions) for more details.\n</P><P>\n  Note: Some external solvers need to write temporary files when they\n  are solving a problem. These are written to the temporary directory\n  specified in ECLiPSe's tmp_dir setting (get_flag/2, set_flag/2).\n\n</P><P>\nListOfOptions are:\n\n<DL>\n\n<P>\n<DT><STRONG><TT>initial_solve(+YesNo)</TT></STRONG>\n    <DD>Specifies if an initial solve (call to the external solver) should\n    be performed immediately after problem setup.\n    YesNo is one of the atoms <TT>yes</TT> or <TT>no</TT>, the default is \n    <TT>yes</TT> if any trigger condition is specified in TriggerModes, \n    <TT>no</TT> if no trigger condition is specified.\n\n<P>\n<DT><STRONG><TT>method(+Method)</TT></STRONG>\n    <DD>Use the specified method (<TT>default, primal, dual, net,\n    barrier, sifting</TT>) (representing Primal Simplex, Dual Simplex,\n    Network Simplex, Barrier, and Sifting respectively) to solve the\n    problem. For MIP problems, this specifies the start algorithm (the one\n    that is used to solve the initial relaxation). See the external\n    solver's manual for a description of these methods.\n<P> \n    For some of the methods, an additional `auxiliary' method may be \n    specified in brackets. These are:\n<DL>\n<P>\n      <DT><TT>net(Simplex)</TT>: \n      <DD>specifies the Simplex method (<TT>primal</TT> or <TT>dual</TT>) to \n      follow the network optimisation. For LP problems only.\n<P>\n      <DT><TT>barrier(Crossover)</TT>: \n      <DD>specifies how the crossover to a basic solution from the barrier\n      solution is performed. <TT>Crossover</TT> can be <TT>primal</TT>, \n      <TT>dual</TT>, or <TT>none</TT>. <TT>none</TT> means no crossover is\n      performed. \n<P>\n      <DT><TT>sifting(SubMethod)</TT>: \n      <DD>specifies the method for solving the sifting subproblem. \n      <TT>SubMethod</TT> can be <TT>primal, dual, net, barrier</TT>.\n<P>\n</DL>\n    For all the auxiliary methods, <TT>default</TT> can also be specified.\n    This is eqivalent to not specifying a auxiliary method at all. \n<P>\n    Note that not all the methods are available on all external solvers. \n    The default method would use the solver's default method to solve the\n    problem. The actual method depends on the external solver. If no method\n    is specified, default is used.\n\n<P>\n<DT><STRONG><TT>node_method(+Method)</TT></STRONG>\n    <DD>For MIP problems only. Use the specified method (<TT>default, primal,\n    dual, net, barrier, sifting</TT>) to solve the subproblem at each node\n    of the MIP search-tree, except the root node, which is specified by\n    <TT>method</TT> option above. See method option for more description of\n    the methods. Note that there are less choices in the specifications of\n    the auxiliary methods that in the method option, due to limitations in\n    the solvers. If a specified auxiliary method cannot be used, `default'\n    will be used instead.\n\n<P>\n<DT><STRONG><TT>solution(+YesNo)</TT></STRONG>\n    <DD>Make the solutions available each time the problem has been (re-)solved\n    successfully.\n    YesNo is one of the atoms <TT>yes</TT> or <TT>no</TT>, the default is \n    <TT>yes</TT>.\n\n<P>\n<DT><STRONG><TT>dual_solution(+YesNo)</TT></STRONG>\n    <DD>Make the dual solutions available each time the problem has been \n    (re-)solved successfully. If the problem is a MIP, then depending on\n    the external solver, this is either unavailable or are the values for\n    the optimal LP node. \n    YesNo is one of the atoms <TT>yes</TT> or <TT>no</TT>, the default is \n    <TT>no</TT>.\n\n<P>\n<DT><STRONG><TT>slack(+YesNo)</TT></STRONG>\n    <DD>Make the constraint slacks available each time the problem has been \n    (re-)solved successfully.\n    YesNo is one of the atoms <TT>yes</TT> or <TT>no</TT>, the default is \n    <TT>no</TT>.\n\n<P>\n<DT><STRONG><TT>reduced_cost(+YesNo)</TT></STRONG>\n    <DD>Make the reduced costs available each time the problem has been \n    (re-)solved successfully. If the problem is a MIP, then depending on\n    the external solver, this is either unavailable or are the values for\n    the optimal LP node. \n    YesNo is one of the atoms <TT>yes</TT> or <TT>no</TT>, the default is \n    <TT>no</TT>.\n\n<P>\n<DT><STRONG><TT>keep_basis(+YesNo)</TT></STRONG>\n    <DD>Store the basis each time the problem has been solved successfully,\n    and use this basis as a starting point for re-solving next time.\n    This option only affects performance.\n    YesNo is one of the atoms <TT>yes</TT> or <TT>no</TT>, the default is \n    <TT>no</TT>.\n\n<P>\n<DT><STRONG><TT>demon_tolerance(RealTol, IntTol)</TT></STRONG>\n    <DD>Specify how far outside a variable's range an lp-solution\n    can fall before lp_demon_setup/5 re-triggers.\n    <TT>RealTol</TT> and <TT>IntTol</TT> are floats and default to\n    0.00001 and 0.5 respectively.\n\n<P>\n<DT><STRONG><TT>sos1(VarList)</TT></STRONG>\n    <DD><TT>VarList</TT> is a list of variables which the solver should\n    treat as variables of a type 1 special ordered set (SOS), i.e. at most\n    one of the variables in the set can be non-zero.\n\n<P>\n<DT><STRONG><TT>sos2(VarList)</TT></STRONG>\n    <DD><TT>VarList</TT> is a list of variables which the solver should\n    treat as variables of a type 2 special ordered set (SOS), i.e. at most\n    two of the variables in the set can be non-zero.\n\n<P>\n<DT><STRONG><TT>presolve(+YesNo)</TT></STRONG>\n    <DD>Specify if the external solver should perform presolve for this\n    problem. With presolving, the external solver will transform the\n    problem before solving it. This can lead to significantly faster times\n    to find solutions. However, as the problem has been transformed, some\n    external solvers have restriction on accessing or changing the problem\n    state. In addition, if the solver is repeatedly called because the\n    problem is frequently modified, then presolve may not be an advantage.\n    YesNo is one of the atoms <TT>yes</TT> or <TT>no</TT>, the default is \n    determined by the global setting of <TT>presolve</TT>, which can be\n    changed via <TT>lp_set/2</TT>. The initial default is <TT>yes</TT>.\n    Note that the presolve setting cannot be changed for a problem once it\n    is set.\n<P>\n<DT><STRONG><TT>timeout(+TimeOut)</TT></STRONG>\n    <DD>Set the external solver to time-out after <TT>TimeOut</TT> seconds.\n    <TT>TimeOut</TT> is a positive number. The solver will abort (in either\n    the abort or suboptimal state, depending on if a suboptimal solution\n    was found) if the optimal solution was not found within the time\n    limit. This should be used instead of setting the solver-specific\n    parameter for time-out directly. In cases where the solver expects an\n    integer for the time-out interval, the time given is rounded up to the\n    next integer value.\n<P>\n<DT><STRONG><TT>suboptimal_handler(+Goal)</TT></STRONG>\n    <DD>Specifies a user defined goal Goal to handle the case when the\n    external solver returned a suboptimal solution (because the problem\n    was aborted). Goal would be run in place of raising the default \n    <TT>eplex_suboptimal</TT> event.\n<P>\n<DT><STRONG><TT>unbounded_handler(+Goal)</TT></STRONG>\n    <DD>Specifies a user defined goal Goal to handle the case when the\n    problem is unbounded. Goal would be run in place of raising the  \n    default <TT>eplex_unknown</TT> event.\n<P>\n<DT><STRONG><TT>unknown_handler(+Goal)</TT></STRONG>\n    <DD>Specifies a user defined goal Goal to handle the case when the\n    external solver was not able to determine if the problem is unbounded\n    or infeasible. Goal would be run in place of raising the default \n    <TT>eplex_unknown</TT> event.\n<P>\n<DT><STRONG><TT>abort_handler(+Goal)</TT></STRONG>\n    <DD>Specifies a user defined goal Goal to handle the case when the\n    external solver aborted without finding any solution. Goal would be \n    run in place of raising the default <TT>eplex_abort</TT> event.\n<P>\n<DT><STRONG><TT>use_var_names(+YesNo)</TT></STRONG>\n    <DD>Specify if variable names (set using <TT>set_var_name/2</TT> of the \n    var_name library) should be passed to the external solver. If a \n    particular variable does not have a name, a solver's default name \n    would be used. Note that for XPRESS-MP, there is a limit on the length\n    of the name, which can be changed between 8 and 64 in steps of 8 with\n    the parameter <TT>mpsnamelength (XPRS_MPSNAMELENGTH)</TT>. Variable \n    names longer than this limit are truncated to the limit. \n    YesNo is one of the atoms <TT>yes</TT> or <TT>no</TT>, the default is \n    <TT>no</TT>.\n<P>\n<DT><STRONG><TT>priority(+Prio)</TT></STRONG>\n  <DD><TT>Prio</TT> is the scheduling priority with which the solver gets\n  woken up.  This priority determines whether the solver is run before or\n  after other constraints. By default, if no priority is specified, the\n  default priority (0, mapped to 5 unless changed) is used. Normally, the\n  default priority should be sufficient and this option is not needed,\n  unless there is a specific need to have the external solver invoked with\n  higher or lower priority than some other constraints.\n<P>\n<DT><STRONG><TT>mip_use_copy(+YesNo)</TT></STRONG>\n    <DD>Some external solvers do not allow a MIP problem to be modified\n    once the MIP search has been started. Eplex works around this\n    problem by making a copy of the problem and solving that, so that\n    the original problem can still be modified. This can be turned off to\n    avoid the overhead of making this copy, in which case the MIP\n    problem cannot be modified. This option is used only when solving a\n    MIP problem, and the external solver does not allow a MIP problem to\n    be modified; otherwise it is ignored.\n    YesNo is one of the atoms <TT>yes</TT> or <TT>no</TT>, the default \n    is <TT>yes</TT> so that the problem can be modified.\n<P>\n<DT><STRONG><TT>write_before_solve(+Format,+File)</TT></STRONG>\n    <DD>This option is most useful for debugging purposes. If given,\n    Eplex will ask the external solver to dump the problem each time\n    the solver is invoked by calling <TT>lp_write/3</TT>. This allows\n    the problem in an <TT>eplex_probe/2</TT> or <TT>lp_probe/3</TT> to\n    be dumped. <TT>Format</TT> and <TT>File</TT> are simply passed to \n    <TT>lp_write/3</TT>.\n<P>\n<DT><STRONG><TT>post_equality_when_unified(+YesNo)</TT></STRONG>\n    <DD>This option determines if an equality constraint between two\n    variables will be posted to the solver when these variables are\n    unified. Setting <TT>YesNo</TT> to no means that the constraint \n    will <EM>not</EM> be posted. Note that this can lead to the\n    solver's problem becoming inconsistent with ECLiPSe's. \n    YesNo is one of the atoms <TT>yes</TT> or <TT>no</TT>, the default is \n    <TT>yes</TT>.\n<P>\n<DT><STRONG><TT>sync_bounds(+YesNo)</TT></STRONG>\n    <DD>This option determines if the bounds of the problems variables are\n    synchronised with other solvers (i.e. the generic bounds are obtained\n    with get_var_bounds/3 and then passed to the external solver) before\n    the external solver is invoked. This was always done for previous\n    non-standalone version of eplex. For standalone eplex, as the bounds\n    are communicated directly to the external solver, the synchronisation\n    of variable bounds is not needed unless the user is using eplex\n    co-operatively with other solvers (e.g. ic). Even in such cases, it may\n    be more efficient to communicate these bounds changes by explicitly\n    programming it, especially if the problem has many variables and bounds\n    changes happen only to a few of the variables. Setting <TT>YesNo</TT>\n    to yes should increase compatibility with previous code (but note that\n    previous eplex obtained the bounds from a specific bounds keeper like\n    ic or range rather than the generic bounds).  YesNo is one of the atoms\n    <TT>yes</TT> or <TT>no</TT>, the default is <TT>no</TT>.\n\n<P>\n<TT>TriggerModes</TT> can be a list of the following specifiers:\n\n<DL>\n\n  <DT><STRONG><TT>inst</TT></STRONG>\n  <DD>re-trigger if a problem variable gets instantiated.\n\n  <DT><STRONG><TT>ModuleName:Index</TT></STRONG>\n  <DD>re-trigger when the  suspension list given by ModuleName:Index is woken\n  for any of the problem variables.\n  The format for <TT>ModuleName:Index</TT> is the same as for specifying\n  the suspension list in suspend/3,4.\n\n  <DT><STRONG><TT>deviating_inst</TT></STRONG>\n  <DD>re-trigger if a problem variable gets instantiated\n      to a value that differs from its lp-solution more than a tolerance.\n\n  <DT><STRONG><TT>bounds</TT></STRONG>\n  <DD>re-trigger each time a variable bound for the solver instance changes.\n\n  <DT><STRONG><TT>deviating_bounds</TT></STRONG>\n  <DD>re-trigger each time a variable's solver instance bound changes\n      such that its lp-solution gets excluded more than a tolerance.\n\n  <DT><STRONG><TT>new_constraint</TT></STRONG>\n  <DD>re-trigger each time a new (arithematic or integral) constraint is\n      added to the solver instance. Note that integral constraint on new \n      problem variables will not re-trigger.\n\n  <DT><STRONG><TT>trigger(Atom)</TT></STRONG>\n  <DD>re-trigger each time the symbolic trigger Atom is pulled by invoking \n      schedule_suspensions/1\n\n  <DT><STRONG><TT>pre(Goal)</TT></STRONG>\n  <DD>an additional condition to be used together with other triggers. When \n      the demon is triggered, it first executes <TT>PreGoal</TT>. Only if \n      that succeeds, does the appropriate external solver get invoked.\n      This provides a way of reducing the number of (possibly expensive)\n      solver invocations when given preconditions are not met.\n\n  <DT><STRONG><TT>post(Goal)</TT></STRONG>\n  <DD>this is not a trigger condition, but specifies a goal to be executed\n      after solver success, but before the Cost variable gets\n      constrained. It is intended as a hook for exporting solution\n      information, e.g. copying solutions from the solver state into\n      variable attributes (eg. tentative value), or computing weights for\n      labeling heuristics from the solver state.  \n  <DT><STRONG><TT>suspension(Susp)</TT></STRONG>\n  <DD>this is not a trigger condition, but instead is used to access the \n      demon used to trigger the solver. Susp is instantiated to\n      the suspension that triggers the solver: by waking Susp, the solver\n      is triggered. Susp is a demon in that it stays around after being\n      woken. Accessing Susp allows the user to specify orbitally conditions \n      for triggering the solver.\n</DL>\n\n  The tolerances mentioned can be specified in lp_setup/4 or lp_set/3\n  as <TT>demon_tolerance</TT>.\n\n</P><P>\n  If several trigger conditions are specified, then any of them will trigger\n  the solver.\n\n</P><P>\n  When a solver demon runs frequently on relatively small problems,\n  it can be important for efficiency to switch off the presolve option\n  to reduce overheads.\n\n</P>")]).
:- comment(eplex_var_get / 3, [template : "EplexInstance:eplex_var_get(+Var, ++What, -Value)", args : ["Var" : "A solver problem variable for solver associated with EplexInstance", "What" : "Specification for information wanted (atom)", "Value" : "Returned value of What"], summary : "Obtain information for an individual solver problem variable Var.", exceptions : [4 : "Handle is not instantiated.", 5 : "Handle is not a compound term.", 6 : "What is not a valid value.", 6 : "Var is not a problem variable for Handle.", 6 : "What is unavailable; the information was not requested at solver setup."], desc : html("<P>\n   Retrieve information about solver state and results related to a\n   particular variable or constraint, for the eplex instance EplexInstance.\n   Fails if no solution has been computed yet.  What can take one of the\n   following values:\n\n<DL>\n    <DT><TT>solution</TT>\n    <DD>Returns the floating-point solution for variable Var.\n<P>\n\n    <DT><TT>typed_solution</TT>\n    <DD>Returns the properly typed (integer or float) solution for variable\n        Var, depending on if the variable was constrained to be an integer\n        or not for EplexInstance.\n<P>\n\n    <DT><TT>reduced_cost</TT>\n    <DD>Returns the reduced cost for variable Var. If the problem is a MIP, \n        then depending on the external solver, this is either unavailable\n        or is the value at the optimal LP node. \n\n</DL>\n<P>\n  Note that solution or reduced_cost can only be retrieved\n  when previously requested in the option list of eplex_solver_setup/4,\n  lp_demon_setup/5, lp_setup/4 or with lp_set/3.\n</P>")]).
:- comment(eplex_var_get_bounds / 3, [template : "EplexInstance: eplex_var_get_bounds(+Var, -Lo, -Hi)", args : ["Var" : "A problem variable for EplexInstance", "Lo" : "Lower bound for Var", "Hi" : "Upper bound for Var"], summary : "Returns the bounds stored in the solver state for Var in eplex instance EplexInstance.", resat : no, exceptions : [5 : "EplexInstance does not a solver setup for it.", 6 : "Var is not a problem variable for EplexInstance."], see_also : [lp_var_get_bounds / 4, eplex_solver_setup / 1, eplex_solver_setup / 4], desc : html("\n    <P>\n    Returns the numeric bounds for Var stored in the solver state\n    associated with the eplex instance EplexInstance. The bounds are\n    returned as floats. Var must be an existing problem variable for\n    EplexInstance. ")]).
:- comment(eplex_write / 2, [template : "EplexInstance:eplex_write(++Format,++File)", args : ["Format" : "lp or mps", "File" : "File name"], see_also : [eplex_read / 2, lp_write / 3, lp_setup / 4], summary : "Write the problem in the solver for eplex instance  EplexInstance to a file.", exceptions : [5 : "EplexInstance does not a solver setup for it."], desc : html("\n   Write the problem in the solver for EplexInstance to a file. The set of\n   supported formats depends on the actual external solver which is used.\n   All solvers support the mps format. Some solvers on some operating\n   system platforms may change or append a suffix to the filename. \n   Note that the mps format does not specify the sense (min or max) of the\n   objective function. Minimisation is also assumed for external solvers\n   that ignore the optimisation direction of the lp file (e.g. Xpress).\n")]).
:- comment(get_changeable_value / 2, [template : "EplexInstance:get_changeable_value(?Var, -Val)", args : ["Var" : "A solver problem variable for solver associated with EplexInstance", "Val" : "The typed_solution value for this variable"], summary : "Interface predicate to access the <EM>changeable</EM> value for this variable."]).
:- comment(instantiation_deviates / 1, [amode : instantiation_deviates(+), args : ["Handle" : "Handle to a solver state"], see_also : [lp_demon_setup / 5], summary : "A trigger goal for lp_demon_setup/5.", desc : html("<P>\n\n  This is intended as a useful pre(Goal) for lp_demon_setup/5 in connection\n  with the <TT>inst</TT> trigger mode.  It succeeds if any of the variables\n  originally involved in Handle have been instantiated to a value that is\n  not within +/- tolerance from the latest simplex solution for that\n  variable.  The admissible tolerances can be specified in lp_setup/4 or\n  lp_set/3 as <TT>demon_tolerance</TT>.\n\n</P>")]).
:- comment(integers / 1, [template : "EplexInstance:integers(?Vars)", args : ["Vars" : "Variable or number, or a list or submatrix of variables/numbers"], see_also : [_10069 : integers / 1, reals / 1, (::) / 2], summary : "Constrains Vars to integers for eplex instance EplexInstance.", desc : html("<P>\tConstrains list Vars to integers in the eplex instance\n        EplexInstance. If a variable in Vars is not already a problem\n        variable for EplexInstance, it will be added as a new problem\n        variable. The external solver will then take the integrality into\n        account, i.e. to solve a MIP/MIQP rather than a relaxed LP/QP\n        problem.  Unlike integers/1 constraints from other solvers, the\n        variables are not constrained to be integer type at the ECLiPSe\n        level. However, when a typed_solution is retrieved (e.g. via\n        eplex_var_get/3), this will be rounded to the nearest integer.\n\t<P>\n\tNote that even when problem variables have been declared as\n        integers in other solvers (ic or other external solver\n        states), if the integrality constraint is not made known to this\n        EplexInstance, any invocation of the eplex external solver (e.g. via\n        eplex_solve/1) will only solve a continuous relaxation.\n\t<P>\n\t")]).
:- comment(lp_add / 3, [amode : lp_add(+, +, +), args : ["Handle" : "Handle to a solver state", "NewNormCons" : "List of new normalised constraints", "NewIntegers" : "List of variables to be considered as integers"], see_also : [lp_setup / 4], resat : no, summary : "Add new constraints to a solver state Handle.", desc : html("<P>\n  Add new normalised constraints (with possibly new variables) to a solver.\n  This is a lower level predicate called by lp_add_constraints/3 and when\n  constraints are collected from the constraints pool by the solver. The\n  constraints are not simplified and must already be normalised, so\n  constraints which would otherwise be simplified away by the higher level\n  predicates can be added to the external solver. The constraints will be\n  removed on backtracking. Note that the solver will not be invoked directly.\n</P><P>\n  Note that variables in NewIntegers can be any problem variables. In\n  previous versions of ECLiPSe, there was a restriction that the variables\n  be new problem variables; this restriction has been removed.\n</P>\n")]).
:- comment(lp_add_columns / 2, [amode : lp_add_columns(+, +), args : ["Handle" : "Handle to a solver state", "Columns" : "A list of Variable:ColumnSpecification pairs."], summary : "Add new variables as columns to the external solver's matrix.", exceptions : [4 : "Handle or Columns are uninstantiated.", 5 : "A Variable in Columns is already a problem variable for problem represented by Handle.", 141 : "Handle is an eplex instance problem, or trigger conditions have been specified."], see_also : [lp_add_constraints / 4], desc : html("<P>\n   Add new variables as columns to the external solver's matrix. This \n   allows non-zero coefficients for the objective and existing constraints\n   to be specified for these variables. \n</P><P>\n   Each column is specified as a Variable:ColumnSpecification pair.\n   Variable is the variable that is being added to the problem, and\n   ColumnSpecification is the specification for the non-zero coefficients\n   for the column representing the variable in the external solver matrix:\n   this is a list of Index:Coefficient pairs. Where index is the index of an\n   existing constraint (obtained when the constraint was added using\n   lp_add_constraints/4), and coefficient is its coefficient. Index\n   can also be the atom 'obj', in which case the coefficient is the objective\n   coefficient for the column. If the objective coefficient is specified,\n   it must be the first element in the ColumnSpecification list. Each\n   constraint coefficient should only occur once. Any index not specified\n   is given a zero value.\n</P><P>\n   Note that lp_add_columns/2 essentially modifies the problem represented\n   by Handle. This is not compatible with the view of the problem as a\n   compound constraint, and therefore, lp_add_columns/2 can only be used\n   for problems that are not eplex instances, and/or have no trigger\n   conditions for triggering the external solver. \n</P>\n  ")]).
:- comment(lp_add_constraints / 3, [amode : lp_add_constraints(+, +, ++), args : ["Handle" : "Handle to a solver state", "Constraints" : "A (possibly empty) list of equality or inequality constraints", "Integers" : "A (possibly empty) list of variables to be considered as integers in the problem"], see_also : [lp_demon_setup / 5, lp_add / 3, lp_add_constraints / 4, eplex_add_constraints / 2, $= / 2, $=< / 2, $>= / 2, (=:=) / 2, (=<) / 2, (>=) / 2], resat : no, fail_if : "Any ground (no variable) or bound constraints (one variable) is self-inconsistent.", exceptions : [4 : "Handle, Constraints or Integers uninstantiated.", 5 : "Some constraint in Constraints is non-linear."], summary : "Add new constraints to the solver Handle, possibly triggering it.", desc : html("<P>\n  Add new constraints (with possibly new variables) to a solver.\n  NewIntegers is a list of variables that the external solver should\n  consider as integers  The new constraints will be taken into\n  account the next time the solver is run: if the new_constraint option of\n  lp_demon_setup was turned on, then the solver will be invoked after the\n  adding of the constraints.  The constraints will be removed on\n  backtracking.\n</P><P>\n  The constraints are normalised and simplified before being passed to\n  the external solver. If any constraint is ground, they are tested for\n  consistency.\n</P><P>\n  Note that variables in NewIntegers can be any problem variables. In\n  previous versions of ECLiPSe, there was a restriction that the variables\n  be new problem variables; this restriction has been removed.\n</P><P>\n\n </P>")]).
:- comment(lp_add_constraints / 4, [amode : lp_add_constraints(+, +, ++, -), args : ["Handle" : "Handle to a solver state", "Constraints" : "A (possibly empty) list of expandable equality or  inequality constraints", "Integers" : "A (possibly empty) list of problem variables to be considered as integers", "Indices" : "Indices for the constraints in Constraints"], see_also : [lp_add_constraints / 3, lp_demon_setup / 5, lp_add / 3, lp_add_columns / 2, $= / 2, $=< / 2, $>= / 2, (=:=) / 2, (=<) / 2, (>=) / 2], resat : no, exceptions : [4 : "Handle, Constraints or Integers uninstantiated.", 5 : "Some constraint in Constraints is ground.", 5 : "Some constraint in Constraints is non-linear."], summary : "Add new expandable constraints to the demon solver Handle.", desc : html("<P>\n  Add new expandable constraints (with possibly new variables) to a solver.\n  An expandable constraint can be expanded when new variables are added to\n  the problem. These constraints are in the form of having a constant on\n  the right-hand side, and coefficients for the problem variables on the\n  left. When new variables are added (via lp_add_columns/2), the\n  coefficients for these variables can be given for the expandable\n  constraints. Note that the constraints can only be expanded if there are\n  no trigger conditions (i.e. the problem must be solved explicitly), or if\n  the problem is not associated with an eplex instance. Otherwise, the\n  added constraints are treated as normal (non-expandable) constraints.\n</P><P>\n  Constraints is a list of expandable constraints.  NewIntegers is a list\n  of variables that the external solver should consider as integers,\n  Indices is a list of the indices for the added constraints. It is\n  returned by the predicate, and has the same length as Constraints. Each\n  element in Indices is the index for the constraint in Constraints at the\n  same position in the list. This index is used to refer to the constraint\n  in lp_add_columns/2.\n</P><P>\n  Operationally lp_add_constraints/4 behaves like lp_add_constraints/3,\n  except that it never trigger the solver as a demon:\n  The new constraints will be taken into account the next time the solver\n  is run, and  removed on backtracking. The constraints are normalised \n  before being passed to the external solver. Unlike lp_add_constraints/3,\n  they are not simplified, and no consistency checks are performed. If any\n  of the constraints are ground, a type error is raised. \n</P><P>\n  Note that variables in NewIntegers can be any problem variables.\n </P>")]).
:- comment(lp_add_indexed / 4, hidden).
:- comment(lp_add_vars / 2, [amode : lp_add_vars(+, +), args : ["Handle" : "Handle to a solver state", "Vars" : "A list of variables or numbers"], summary : "Declare Vars to be problem variables for the solver state Handle", see_also : [lp_setup / 4, lp_demon_setup / 5], desc : html("<P>\n   Declares variables in Vars as problem variables for the solver state\n   represented by Handle. Any of the variables that are not existing \n   problem variables for Handle are added to the problem. The new\n   variables' bounds are constrained to -infinity..infinity (infinity as \n   defined by the external solver).\n"), fail_if : "Vars contain elements which are neither variables or numbers."]).
:- comment(lp_cleanup / 1, [amode : lp_cleanup(+), args : ["Handle" : "Handle to a solver state"], summary : "Destroy the specified solver Handle and clean up.", desc : html("<P>\n    Destroy the specified solver, free all memory, etc.  Note that ECLiPSe\n    will normally do the cleanup automatically, for instance when execution\n    fails across the solver setup, or when a solver handle gets garbage\n    collected.  However, calling lp_cleanup/1 explicitly does not hurt and\n    may cause resources (memory and licence) to be freed earlier.\n</P>")]).
:- comment(lp_demon_setup / 5, [amode : lp_demon_setup(+, ?, ++, ++, -), args : ["Objective" : "Objective function: min(CostExpr) or max(CostExpr)", "Cost" : "Variable bounded by the optimal solution", "ListOfOptions" : "List of solver options", "TriggerModes" : "List of conditions for re-triggering solver", "Handle" : "handle to solver state"], see_also : [lp_solve / 2, lp_set / 3, lp_setup / 4, solution_out_of_range / 1, schedule_suspensions / 1, library(constraint_pools)], summary : "Setup the external solver as a simplex demon.", eg : "   Some common invocations patterns for this predicate are the following.\n   The first triggers the solver only on instantiation of variables to\n   values that don't fit with the simplex solution:\n\n      lp_demon_setup(min(Expr), C, [], [deviating_inst], H)\n\n", desc : html("<P>\n  Setup the external solver as a simplex demon. A simplex demon collects\n  linear constraints and re-solves the problem whenever the triggering\n  conditions in TriggerModes are met.\n\n</P><P>\n  Declaratively, this can be seen as a compound constraint representing all\n  the individual linear constraints that have been set so far and are going\n  to be set up later.  Operationally, the delayed constraints are collected\n  and an external solver is set up (as with lp_setup/4).  Then the problem\n  is solved once initially (if <TT>initial_solve</TT> option is yes) and a\n  delayed goal lp_demon is set up which will re-trigger the solver when \n  certain  conditions are met.\n\n</P><P>\n  <TT>CostExpr</TT> is a linear cost expression (or quadratic, if supported\n  by the external solver).\n\n</P><P>\n  <TT>Handle</TT> refers to the created solver state (as in lp_setup/4 or\n  lp_read/3 described below). It can be used to access and modify the state\n  of the solver, retrieve solution information etc. \n\n</P><P>\n  Unlike with lp_solve/2, <TT>Cost</TT> will not be instantiated to a\n  solution's cost, but only be bounded by it (if the solution is optimal):\n  For a minimization problem, each solution's cost becomes a lower bound,\n  for maximization an upper bound on Cost.  This technique allows for\n  repeated re-solving with reduced bounds or added constraints. Note that\n  Cost is not automatically made a problem variable (it can be a problem\n  variable if there are constraints that involve it), and thus may not have\n  bounds associated with in. In order for the bounds information not to be\n  lost, some bounds should be given to <TT>Cost</TT> (e.g. making it a\n  problem variable (but this might introduce unecessarly self-waking on\n  bounds change), or via another solver with bounds (e.g. ic)).\n</P><P>\n  <TT>ListOfOptions</TT> is a list of solver options as described for\n  lp_setup/4. In addition, the following extra options are also available:\n   \n<DL>\n\n<DT><STRONG><TT>collect_from(+Pool)</TT></STRONG>\n    <DD>Specifies if this solver state should be associated with an eplex\n    instance. If Pool is <TT>none</TT>, then the solver is not associated\n    with an eplex instance. If Pool is <TT>pool(Instance)</TT>, where\n    Instance is the (atomic) name of an existing eplex instance, then this\n    eplex instance would be associated with the solver state, i.e. when the\n    solver is invoked, it will collect constraints posted to\n    <TT>Instance</TT>.  Note that <TT>Instance</TT> must not be associated\n    with any other solver state already.\n</P><P>\n    The default value for <TT>Pool</TT> is pool(eplex) (for backward\n    compatibility).\n\n<P>\n<DT><STRONG><TT>initial_solve(+YesNo)</TT></STRONG>\n    <DD>Specifies if an initial solve (call to the external solver) should\n    be performed immediately after problem setup.\n    YesNo is one of the atoms <TT>yes</TT> or <TT>no</TT>, the default is \n    <TT>yes</TT> if any trigger condition is specified in TriggerModes, \n    <TT>no</TT> if no trigger condition is specified.\n</DL>\n   \n</P><P>\n\n  <TT>TriggerModes</TT> specifies under which conditions the solver demon\n  will be re-triggered. It can be a list of the following specifiers\n\n<DL>\n\n  <DT><STRONG><TT>inst</TT></STRONG>\n  <DD>re-trigger if a problem variable gets instantiated.\n\n  <DT><STRONG><TT>ModuleName:Index</TT></STRONG>\n  <DD>re-trigger when the  suspension list given by ModuleName:Index is woken\n  for any of the problem variables.\n  The format for <TT>ModuleName:Index</TT> is the same as for specifying\n  the suspension list in suspend/3,4.\n\n  <DT><STRONG><TT>deviating_inst</TT></STRONG>\n  <DD>re-trigger if a problem variable gets instantiated\n      to a value that differs from its lp-solution more than a tolerance.\n\n  <DT><STRONG><TT>bounds</TT></STRONG>\n  <DD>re-trigger each time a variable bound for the solver instance changes.\n\n  <DT><STRONG><TT>deviating_bounds</TT></STRONG>\n  <DD>re-trigger each time a variable's solver instance bound changes\n      such that its lp-solution gets excluded more than a tolerance.\n\n  <DT><STRONG><TT>new_constraint</TT></STRONG>\n  <DD>re-trigger each time a new (arithematic or integral) constraint is\n      added to the solver instance. Note that integral constraint on new \n      problem variables will not re-trigger.\n\n  <DT><STRONG><TT>trigger(Atom)</TT></STRONG>\n  <DD>re-trigger each time the symbolic trigger Atom is pulled by invoking \n      schedule_suspensions/1\n\n  <DT><STRONG><TT>pre(Goal)</TT></STRONG>\n  <DD>an additional condition to be used together with other triggers. When \n      the demon is triggered, it first executes <TT>PreGoal</TT>. Only if \n      that succeeds, does the appropriate external solver get invoked.\n      This provides a way of reducing the number of (possibly expensive)\n      solver invocations when given preconditions are not met.\n\n  <DT><STRONG><TT>post(Goal)</TT></STRONG>\n  <DD>this is not a trigger condition, but specifies a goal to be executed\n      after solver success, but before the Cost variable gets\n      constrained. It is intended as a hook for exporting solution\n      information, e.g. copying solutions from the solver state into\n      variable attributes (eg. tentative value), or computing weights for\n      labeling heuristics from the solver state.  \n  <DT><STRONG><TT>suspension(Susp)</TT></STRONG>\n  <DD>this is not a trigger condition, but instead is used to access the \n      demon used to trigger the solver. Susp is instantiated to\n      the suspension that triggers the solver: by waking Susp, the solver\n      is triggered. Susp is a demon in that it stays around after being\n      woken. Accessing Susp allows the user to specify orbitally conditions \n      for triggering the solver.\n</DL>\n\n  The tolerances mentioned can be specified in lp_setup/4 or lp_set/3\n  as <TT>demon_tolerance</TT>.\n\n</P><P>\n  If several trigger conditions are specified, then any of them will trigger\n  the solver.\n\n</P><P>\n  When a solver demon runs frequently on relatively small problems,\n  it can be important for efficiency to switch off the presolve option\n  to reduce overheads.\n\n</P><P>\n  The solver demon calls lp_solve/2 when it wakes up. See the description\n  of lp_solve/2 for the handling of exceptions.\n</P><P>\n  Note: Some external solvers need to write temporary files when they\n  are solving a problem. These are written to the temporary directory\n  specified in ECLiPSe's tmp_dir setting (get_flag/2, set_flag/2).\n</P>")]).
:- comment(lp_get / 2, [amode : lp_get(++, -), amode : lp_get(++, +), args : ["ParamName" : "Atom", "Value" : "Variable, integer, float or atom"], summary : "Obtain the value of a global parameter.", see_also : [lp_set / 2], desc : html("    Eplex have a number of global (i.e. not specific to a\n    particular problem) parameters. These can be queried using this \n    predicate.\n<DL>\n    <DT><TT>optimizer</TT>\n\t<DD>Returns the name of the external solver, currently\n\t'cplex' or 'xpress'.\n    <DT><TT>optimizer_version</TT>\n\t<DD>Returns an integer derived from the version of the\n\texternal solver.\n    <DT><TT>presolve</TT>\n\t<DD>Returns the default presolve setting for solver setup, i.e. the\n        presolve setting that a solver state would be given if it was not\n        directly specified during setup. The value is 1 if the default is\n        to have presolve on, and 0 if off. Note that this is a change from\n        previous versions of eplex, where this parameter is directly\n        connected to the external solver's own presolve parameter. However,\n        the solver may have more than one parameter for presolve settings,\n        and these may take on more values than 0 and 1. In such cases,\n        eplex will set the parameters(s) to some default value(s)\n        corresponding to presolve being off and on. These parameters can be\n        accessed directly using the optimizer_param option if required.\n    <DT><TT>timeout</TT>\n        <DD>Returns the default time-out setting that a solver state would\n        be given if it was not directly specified during setup. Value is\n        0 if there is no time-out.\n    <DT><TT>standalone</TT>\n        <DD>Value is `yes', as this is the stand-alone version of Eplex.\n        as the external solver is used for keeping the bounds. This option\n        allows programmer to write code that needs to distinguish between\n        the stand-alone and the non-stand-alone versions of Eplex.\n    <DT><TT>optimizer_param(Param)</TT>\n        <DD>Get the Value of the external solver's parameter <TT>Param</TT>.\n        The exact behaviour and available parameters are dependent on the \n        external solver: if the external solver has only problem specific \n        parameters (e.g. XPRESS-MP 13 and later), this gets the default \n        setting that would be used for new problems; if the external solver\n        has global parameters, this gets the global value for the parameter.\n        If Param is not a valid parameter for the solver, an out of range \n        error is raised. See lp_get/3 for more details on the parameters. \n</DL>\n")]).
:- comment(lp_get / 3, [amode : lp_get(+, ++, -), args : ["Handle" : "Handle to an existing solver state", "ParamName" : "Name of parameter (atom or structure)", "Value" : "Returned value for ParamName"], summary : "Retrieve information about solver state and results for solver state Handle.", see_also : [lp_setup / 4, lp_set / 3, eplex_get / 2, lp_add_constraints / 4], desc : html("<P>\n   Retrieve information about solver state and results for the solver state\n   represented by <TT>Handle</TT>. <TT>ParamName</TT> is the same as that\n   for eplex_get/2, which retrieves the same information via the EplexInstance.\n   It can  be one of:\n</P>\n\n<DL>\n<P>  \n     <DT><STRONG><TT>vars</TT></STRONG>\n     <DD>Returns a term ''(X1,...,Xn) whose arity is the number of\n         variables involved in the solver's constraint set, and whose\n         arguments are these variables.\n\n<P>\n     <DT><STRONG><TT>ints</TT></STRONG>\n     <DD>Returns a list [Xi1,...,Xik] which is the subset of the problem\n         variables that the solver considers to be integers.\n\n<P>\n     <DT><STRONG><TT>constraints_norm</TT></STRONG>\n     <DD>Returns a list of the problem constraints in normalised form.\n         They may be simplified with respect to the original set that \n         was passed to lp_setup/4.\n\n<P>\n     <DT><STRONG><TT>constraints</TT></STRONG>\n     <DD>Returns a list of the problem constraints in denormalised (readable)\n         form.  They may be simplified with respect to the original set\n         that was passed to lp_setup/4.\n\n<P>\n     <DT><STRONG><TT>objective</TT></STRONG>\n     <DD>Returns a term min(E) or max(E), representing objective function\n         and optimisation direction. E is a linear expression: any\n         quadratic components will not be retrieved.\n\n<P>\n     <DT><STRONG><TT>num_cols</TT></STRONG>\n     <DD>Returns the number of columns (i.e. variables) in the matrix of the\n     solver state.\n\n<P>\n     <DT><STRONG><TT>num_rows</TT></STRONG>\n     <DD>Returns the number of rows (i.e. constraints) in the matrix of the\n     solver state.\n\n<P>\n     <DT><STRONG><TT>num_nonzeros</TT></STRONG>\n     <DD>Returns the number of non-zero coefficients in the matrix of the\n     solver state.\n\n<P>\n     <DT><STRONG><TT>num_ints</TT></STRONG>\n     <DD>Returns the number of columns (i.e. variables) constrained to be\n     integers in the matrix of the solver state.\n\n<P>\n     <DT><STRONG><TT>num_quads</TT></STRONG>\n     <DD>Returns the number of non-zero coefficients in the quadratic\n     coefficient matrix (Q-matrix) of the solver state.\n\n<P>\n     <DT><STRONG><TT>method</TT></STRONG>\n     <DD>Returns the method that is specified to solve the problem. If an\n     auxiliary  method can be given for the method, and this auxiliary\n     method is not <TT>default</TT>, the method will be returned as \n     Method(Aux), e.g. <TT>barrier(none)</TT>. The method will be \n     <TT>default</TT> unless otherwise specified by the the user (at setup or \n     via eplex_setup/2 or lp_setup/3).\n     In case of MIP solving, this is the start algorithm (the one that \n     is used to solve the initial relaxation).\n\n<P>\n     <DT><STRONG><TT>node_method</TT></STRONG>\n     <DD>Applicable to MIP problems only. Returns the method that is\n     specified to solve the problem at the nodes of the branch-and-bound\n     tree. If an auxiliary method can be given for the method, and this\n     auxiliary method is not <TT>default</TT>, the method will be returned\n     as Method(Aux), e.g. <TT>barrier(none)</TT>. The method will be\n     <TT>default</TT> unless otherwise specified by the the user (at setup\n     or via eplex_setup/2 or lp_setup/3).\n     Note that the method for solving the root (initial relaxation) node\n     is specified by <TT>method</TT>.\n\n<P>\n     <DT><STRONG><TT>status</TT></STRONG>\n     <DD>Status that was returned by the most recent invocation of the \n         external solver.\n\n<P>\n     <DT><STRONG><TT>cost</TT></STRONG>\n     <DD>Cost of the current solution.\n         Fails if no solution has been computed yet.\n\n<P>\n     <DT><STRONG><TT>typed_solution</TT></STRONG>\n     <DD>Returns a term ''(X1,...,Xn) whose arguments are the properly\n         typed (integer or float) solution values for the corresponding\n         problem variables (<TT>vars</TT>).  The floating point solutions\n         are the same as returned by <TT>solution</TT>, the integers are\n         obtained by rounding the corresponding floating-point solution to\n         the nearest integer.  To instantiate the problem variables to\n         their solutions, unify this term with the corresponding term\n         containing the variables:\n\n<PRE>\n    instantiate_solution(Handle) :-\n        lp_get(Handle, vars, Vars),\n        lp_get(Handle, typed_solution, Values),\n        Vars = Values.\n</PRE>\n\n<P>\n    <DT><STRONG><TT>slack</TT></STRONG>\n\n    <DD>Returns a list of floating-point values representing the constraint\n        slacks. The order corresponds to the list order in\n        <TT>constraints</TT>.  Fails if no solution has been computed yet.\n\n<P>\n    <DT><STRONG><TT>slack(Indexes)</TT></STRONG>\n    <DD>Returns a list of floating-point values representing the slack\n        values for the constraints represented by Indexes. Indexes are \n        a list of constraint indecies (as returned by lp_add_constraints/4),\n        and the order of the returned list corresponds to the order in\n        <TT>Indexes</TT>.  Fails if no solution has been computed yet,\n        or if the slack option was not set to yes.\n\n<P>\n    <DT><STRONG><TT>dual_solution</TT></STRONG>\n    <DD>Returns a list of floating-point values representing the dual\n        solutions.  The order corresponds to the list order in\n        <TT>constraints</TT>.  Fails if no solution has been computed yet.\n\n<P>\n    <DT><STRONG><TT>dual_solution(Indexes)</TT></STRONG>\n    <DD>Returns a list of floating-point values representing the dual\n        solutions for the constraints represented by Indexes. Indexes are\n        a list of constraint indecies (as returned by lp_add_constraints/4),\n        and the order of the returned list  corresponds to the order in\n        <TT>Indexes</TT>.  Fails if no solution has been computed yet,\n        or if the dual_solution option was not set to yes.\n\n<P>\n    <DT><STRONG><TT>demon_tolerance</TT></STRONG>\n    <DD>Returns a comma-separated pair <TT>(RealTol,IntTol)</TT> of\n        floating-point values which specify how far outside a variable's\n        range an lp-solution can fall before lp_demon_setup/5\n        re-triggers. The tolerances differ for real (default 0.00001) and\n        integer (default 0.5) variables.\n\n<P>\n    <DT><STRONG><TT>simplex_iterations</TT></STRONG>\n    <DD>Returns the external solver's count of simplex iterations.\n\n<P>\n    <DT><STRONG><TT>node_count</TT></STRONG>\n    <DD>Returns the external MIP solver's node count.\n\n<P>\n    <DT><STRONG><TT>statistics</TT></STRONG>\n    <DD>Returns a list of counter values <TT>[Successes, Failures,\n        Aborts]</TT>, indicating how often lp_solve/2 was invoked on the\n        Handle, and how many invocations succeeded, failed and aborted\n        respectively.\n\n<P>\n    <DT><TT>timeout</TT></STRONG>\n    <DD>Returns the time-out value for the solver state. This is the amount\n        of CPU time in seconds that the external solver will be allow to\n        spend solving the problem before timing out. The value is 0 if \n        no time-out has been set.\n<P>\n     <DT><STRONG><TT>optimizer_param(Param)</TT></STRONG>\n     <DD>Returns the value of the external solver's parameter Param\n         for the problem represented by Handle. The external solver \n         has a number of parameters that affect the way they work, and \n         this queries their values. If Param is not a valid parameter for\n         the solver, an out of range exception is raised. See below for \n         more details on the parameters.\n<P>\n    <DT><STRONG><TT>post_equality_when_unified</TT></STRONG>\n    <DD>Returns the value (yes or no) if an equality constraint will be\n        posted to a solver if two variables in the solver's problem are \n        unified. \n<P>\n    <DT><STRONG><TT>pool</TT></STRONG>\n    <DD>Returns the name of the eplex instance (if any) associated with \n        the solver state. Fails otherwise. Only useful if called with \n        lp_get/3.\n<P>\n    <DT><STRONG><TT>handle</TT></STRONG>\n    <DD>Returns the solver state handle (if any) associated with the eplex \n        instance. Fails otherwise. Only useful if called with eplex_get/2.\n<P>\n</DL>\nNote that reduced_cost, slack, dual_solution can only be retrieved\nwhen previously requested in the option list of lp_setup/4 or with lp_set/3.\n\n<P>\nFor the external solver's control parameter specified by\noptimizer_param(Param), Param must be an atom. The Value returned is\neither an integer, float or atom, depending on the parameter. The parameter\nis generally specific to a solver and version, and also, they may be\nproblem specific, or global, again depending on the solver version. In all\ncases, the value returned by lp_get/3 is the current value for the parameter\nfor the problem Handle. Refer to the solver documentation for details on the \nparameters. The names of the parameters are derived from the names of the \nparameters in the external solver. For CPLEX, take the parameter name from the CPLEX manual (or cplex.h), remove the CPX_PARAM_ prefix and convert the \nrest to lower case, e.g.\n\n<PRE>\n        CPX_PARAM_NODELIM becomes nodelim. \n</PRE>\nFor XPRESS-MP (version 13 and newer), take the parameter name from the \nmanual (or xpresso.h), remove the XPRS_ prefix (if present) and convert \nthe rest to lower case, e.g.\n<PRE>\n\tMAXNODE or XPRS_MAXNODE becomes maxnode. \n</PRE>\n    (pre version 13, the parameter names are prefixed by N_ instead of XPRS_).\n\n<P>\n    The following parameter names are additional aliases that work for\n    either solver:\n<DL>\n    <DT><TT>crash</TT>\n\t<DD>CPX_PARAM_CRAIND (CPLEX) or XPRS_CRASH (XPRESS-MP) -integer\n    <DT><TT>feasibility_tol</TT>\n\t<DD>CPX_PARAM_EPRHS (CPLEX) or XPRS_FEASTOL (XPRESS-MP) - float\n    <DT><TT>integrality</TT>\n\t<DD>CPX_PARAM_EPINT (CPLEX) or XPRS_MIPTOL (XPRESS-MP) - float\n    <DT><TT>iteration_limit</TT>\n\t<DD>CPX_PARAM_ITLIM (CPLEX) or XPRS_LPITERLIMIT (XPRESS-MP) -integer\n    <DT><TT>node_limit</TT>\n\t<DD>CPX_PARAM_NODELIM (CPLEX) or XPRS_MAXNODE (XPRESS-MP) -integer\n    <DT><TT>objdifference</TT>\n\t<DD>CPX_PARAM_OBJDIF (CPLEX) or XPRS_MIPADDCUTOFF (XPRESS-MP) - float\n    <DT><TT>refactor</TT>\n\t<DD>CPX_PARAM_REINV (CPLEX) or XPRS_INVERTFREQ (XPRESS-MP) -integer\n    <DT><TT>scrind</TT>\n\t<DD>CPX_PARAM_SCRIND (CPLEX) or XPRS_OUTPUTLOG (XPRESS-MP) -integer\n</DL>\n\n")]).
:- comment(lp_get_changeable_value / 3, [template : "EplexInstance:get_changeable_value(+Handle, ?Var, -Val)", args : ["Handle" : "Handle to an eplex instance", "Var" : "A solver problem variable for solver associated with EplexInstance", "Val" : "The typed_solution value for this variable"], summary : "Interface predicate to access the <EM>changeable</EM> value for this variable."]).
:- comment(lp_get_license / 0, [summary : "Get a runtime license token for the external solver.", fail_if : "Fails if no license can (currently) be obtained", see_also : [lp_get_license / 2, lp_release_license / 0], desc : html("    \tThe eplex-library interfaces to an external simplex/MIP solver\n\twhich might require a license to run (e.g. CPLEX, XPRESS-MP).\n\tWhen the eplex-library is loaded, it tries to obtain a license\n\timmediately.  If this is not possible, for example because the\n\tlicense pool is temporarily empty, a warning is printed. The\n\tapplication program should then call lp_get_license/0 later\n\tto obtain a license before any eplex functionality is used.\n\tIf a license is successfully obtained or already held,\n\tlp_get_license succeeds, otherwise it fails.\n    <P>\n    \tThis predicate uses information from the file eplex_lic_info.ecl\n\tin the ECLiPSe library directory, or solver specific environment\n\tvariable settings to locate the licensing information.\n    ")]).
:- comment(lp_get_license / 2, [amode : lp_get_license(+, +), args : ["LicStr" : "String or Atom", "LicNum" : "Integer"], summary : "Get a runtime license token for the external solver.", fail_if : "Fails if no license can (currently) be obtained", see_also : [lp_get_license / 0, lp_release_license / 0, lp_get_license_challenge / 1], desc : html("    \tThe eplex-library interfaces to an external simplex/MIP solver\n\twhich might require a license to run (e.g. CPLEX, XPRESS-MP).\n\tWhen the eplex-library is loaded, it tries to obtain a license\n\timmediately.  However, this might not be possible, either\n\tbecause no licenses are currently available, or because\n\tspecific licensing information needs to be supplied.\n    <P>\n\tIn the latter case, lp_get_license/2 must be called explicitly\n\tby the programmer, and the relevant licensing information must\n\tbe supplied as arguments.  The meaning of the arguments is\n\tspecific to the solver used:\n    <PRE>\n                                LicStr          LicNum\n\n        CPLEX development       unused          unused\n        CPLEX runtime           licenvstring    serialnum\n        XPRESS-MP development   xpress_path     unused\n        XPRESS-MP runtime       xpress_path     response\n    </PRE>\n        If LicStr is a file or directory name, it is expected to be in\n\tthe native operating system syntax.\n    ")]).
:- comment(lp_get_license_challenge / 1, [amode : lp_get_license_challenge(-), args : ["Challenge" : "Variable"], summary : "Get parameter for computing license key (some external solvers only)", fail_if : "Fails if the solver doesn't use a challenge-response licensing system", see_also : [lp_get_license / 2], eg : "\n     ?- ( lp_get_license_challenge(Challenge) ->\n\t    magic_formula(Challenge, Response),\n\t    lp_get_license(RuntimeLicenseString, Response)\n\t;\n\t    lp_get_license(DevelopmentLicensePath, 0)\n\t).\n    ", desc : html("\tThis is only needed for certain OEM versions of external solvers!\n    <P>\n    \tThe eplex-library interfaces to an external simplex/MIP solver\n\twhich might require a license to run (e.g. CPLEX, XPRESS-MP).\n\tCertain versions of these external solvers use a challenge-\n\tresponse licensing system. Only in such cases is this predicate\n\tneeded. lp_get_license_challenge/1 returns a value which is used to\n\tcompute a license key. This key is then passed into lp_get_license/2.\n\tFor the details of this procedure you will need to consult the\n\tdocumentation of the solver vendor.\n    <P>\n        Be aware that the magic formula supplied by the vendor is usually\n        designed to be performed in a language like C, and may rely on the\n        behaviour of overflowing with 32 bit integers. In ECLiPSe, no\n        overflowing will takes place because of bignums, and this has to be\n        taken into account if the magic formula is calculated in ECLiPSe.\n    <P>\n\tIf you have a development license of CPLEX or XPRESS-MP, this\n\tpredicate does not need to be called. If called anyway, it fails.\n    ")]).
:- comment(lp_probe / 3, [amode : lp_probe(+, +, -), args : ["Handle" : "Handle to existing solver state", "Probes" : "Temporary probe specification(s)", "Cost" : "Value of solution"], summary : "Invoke external solver, probing the problem temporary modified by the probe specifications.", see_also : [lp_solve / 2, lp_setup / 4, lp_var_get / 4, lp_get / 3, lp_set / 3], desc : html("<P>\n   Similar to lp_solve/2, but the problem is first temporarily modified\n   as specified in Probes. Probes is a list of one or more probe\n   specification that specifies how the problem is modified. After the call\n   to this predicate, the problem is restored for the external\n   solver. However, the result from the probe (obtainable from\n   lp_var_get/4 and lp_get/3) are retained.\n</P><P>\n   The following probe specifcations are allowed:\n<DL>\n    <DT>min(Expr)/max(Expr)<DD>\n        Minimise/maximise the problem with the objective function Expr.\n        Only existing problem variables can be given in Expr. Cannot be\n        used in conjunction with objsense or objexpr.\n    <DT>objsense(Sense)<DD>\n        Sense is either min or max. Solves the problem with the original\n        objective function, but with the sense given in Sense rather than\n        that specified at setup. If only the sense of the objective is to \n        be changed, this changes the objective more efficiently than using\n        min(Expr)/max(Expr). Cannot be used in conjunction with min/max or\n        objexpr.\n    <DT>objexpr(Expr)<DD>\n        Optimise the problem with respect to the objective function Expr,\n        without changing the optimisation direction specified at problem\n        setup. Cannot be used in conjunction with objsense or min/max.\n    <DT>fixed<DD>\n        The problem is solved as an LP problem by `fixing' the integer\n        variables to their optimal MIP solution values. If there is an\n        existing MIP solution for the problem, eplex will try to use that;\n        otherwise, the problem is first solved as a MIP problem\n        first. `Fixed' probing is useful for providing reduced costs for\n        MIP problems. Note that reduced costs for the variables are only be\n        available if the reduced_cost option is set to yes for the problem\n        (this can be done either at problem setup, or by using\n        eplex_set/2). For a problem without integer variables, the original\n        problem is solved without change.  Note that this probe\n        specification is not available if the mip_use_copy option is set to\n        no for external solvers that cannot modify a MIP problem.  Cannot\n        be used in conjunction with `relaxed'.\n    <DT>relaxed<DD>\n        The problem is solved as an LP problem by relaxing all the integer\n        constraints.  For a problem with integer variables, this should be\n        equivalent to the initial relaxation solved at the start of the MIP\n        search. Depending on the solver, the discreteness of the integer\n        variables may still be taken into account during presolve. To\n        ensure that the problem solved is exactly the LP problem without\n        any integer constraints, presolve should be off. For a problem\n        without integer variables, the original problem is solved without\n        change. Note that this probe specification is not available if the\n        mip_use_copy option is set to no for external solvers that cannot\n        modify a MIP problem. Cannot be used in conjunction with `fixed'.\n\n</P>"), fail_if : "External solver was unable to find a solution.", exceptions : [5 : "EplexInstance does not a solver setup for it.", eplex_suboptimal : "Solution was found, but is possibly suboptimal", eplex_unbounded : "Problem is unbounded, no solution values", eplex_unknown : "Result is unknown (infeasible or unbounded)", eplex_abort : "External solver aborted for some reason", 6 : "mip_use_copy option was set to no (solver dependent) for probes that require yes."]]).
:- comment(lp_read / 3, [amode : lp_read(+, ++, -), args : ["File" : "File name", "Format" : "lp or mps", "Handle" : "Returns a handle to the new solver state"], see_also : [lp_write / 3, lp_setup / 4, eplex_read / 2, eplex_write / 2, lp_probe / 3], summary : "Read a problem from a file and setup a solver for it.", desc : html("\n   Read a problem from a file and setup a solver for it.  Format is\n   lp or mps. The result is a handle similar to the one obtained by \n   lp_setup/4. Note that minimisation of the objective is assumed \n   for mps format, as the sense of the objective is not included in \n   the mps format. Minimisation is also assumed for external solvers\n   that ignore the optimisation direction of the lp file (e.g. Xpress).\n   Note also that although quadratic problems can be read in correctly if\n   supported by the external solver, the quadratic objective coefficients\n   are not extracted from the problem by eplex. These coefficients are\n   used to set/reset the objective when a problem is probed with a\n   different objective in eplex_probe/2 or lp_probe/3, so the objective\n   will not be changed or restored correctly in this case.\n")]).
:- comment(lp_release_license / 0, [summary : "Release a runtime license token for the external solver.", see_also : [lp_get_license / 0, lp_get_license / 2], desc : html("    \tThe eplex-library interfaces to an external simplex/MIP solver\n\twhich might require a license to run (e.g. CPLEX, XPRESS-MP).\n\tWhen the eplex-library is loaded, it tries to obtain a license\n\timmediately, or a license can be obtained by calling\n\tlp_get_license/0.  A held license can then be released using\n\tlp_release_license/0.  The predicate always succeeds, even\n\tif no license was held.\n    ")]).
:- comment(lp_set / 2, [amode : lp_set(++, ++), args : ["ParamName" : "Atom", "Value" : "Integer, float, string or structure"], see_also : [lp_get / 2], resat : no, summary : "Set a global parameter for the external solver.", desc : html("\n<P>\n    Set a global parameter. The parameter names are the same as described\n    in lp_get/2. For the timeout parameter, Value can be of any numeric\n    type. Note that for the external solver's parameters (set via\n    optimizer_param(Param)), the exact behaviour is solver dependent: if\n    the solver has global parameters, this sets the value of the parameter\n    globally; otherwise, this sets the default value of the parameter that\n    would be assigned to a new problem. The setting is <EM>not</EM> undone \n    on backtracking.\n\n</P><P>\n    This behaviour was changed from that of previous (pre 5.4) versions of\n    ECLiPSe, as all solvers had global parameters, and thus there were no\n    setting of default values. Code developed under these older versions\n    may no longer be setting the external solver's parameters correctly.\n    Thus when lp_set/2 sets a default setting, an event lp_set_default_warning\n    is raised to warn the user about the difference. This event can be \n    suppressed by the directive \n<PRE>        \n        :- set_event_handler(lp_set_default_warning, true/0)\n</PRE>\n\n</P><P>\n    In addition, lp_set/2 is used to control the output from the external \n    solver:\n<DL>\n    <DT><TT>lp_set(SolverChannel, +(Stream))</TT>\n       <DD>Send output from SolverChannel to the ECLiPSe I/O stream Stream.\n    <DT><TT>lp_set(SolverChannel, -(Stream))</TT>\n       <DD>Stop sending output from SolverChannel to the ECLiPSe I/O stream \n       Stream.\n</DL>\n    SolverChannel is one of <TT>result_channel, error_channel, warning_channel, \n    log_channel</TT>, and Stream is an ECLiPSe stream identifier (e.g. \n    <TT>output</TT>, or the result of an open/3 operation).\n<P>\n    By default, <TT>error_channel</TT> is directed to ECLiPSe's\n    <TT>error</TT> stream, <TT>warning_channel</TT> to <TT>warning_output</TT>\n    while <TT>result_channel</TT> and <TT>log_channel</TT> are suppressed.\n    To see the output on these channels, do\n</P>\n<TT><PRE>\n   :- lp_set(result_channel, +output).\n   :- lp_set(log_channel, +log_output).\n</PRE></TT>\n<P>\nSimilarly, to create a log file:\n<TT><PRE>\n   :- open('mylog.log', write, logstream), lp_set(log_channel, +logstream).\n</PRE></TT>\nand to stop logging:\n<TT><PRE>\n   :- lp_set(log_channel, -logstream), close(logstream).\n</PRE></TT>\n</P>")]).
:- comment(lp_set / 3, [amode : lp_set(+, ++, +), args : ["Handle" : "Handle to a solver state", "What" : "Option to set", "Value" : "Value being set"], resat : no, summary : "Change initial options for solver state Handle.", see_also : [lp_setup / 4, lp_get / 3, lp_var_get / 4, eplex_set / 2], desc : html("<P>\nThis primitive can be used to change some of the initial options\neven after setup. \n<EM>Handle</EM> refers to an existing solver state,\n<EM>What</EM> can be one of the following:\n\n\n<DL>\n    <DT><STRONG><TT>method</TT></STRONG>\n        <DD>Set the method that will be used to solve the problem.  Value\n        is one of <TT>default, primal, dual, net, net(Simplex), barrier,\n        barrier(Crossover), sifting, sifting(SubMethod)</TT>. Simplex can\n        be one of <TT>default, primal, dual</TT>, specifying the Simplex\n        method to use in the Network Simplex algorithm. Crossover can be\n        one of <TT>default, primal, dual, none</TT>, specifying the\n        crossover method to use for the barrier method. SubMethod could be\n        one of default, primal, dual, net, barrier</TT>, specifying the\n        method to use for the subproblems in the sifting method. Note that\n        some of these methods may not be available on all external solvers.\n        In case of MIP solving, this is the start algorithm (the one that\n        is used to solve the initial relaxation). \n\n<P>\n    <DT><STRONG><TT>node_method</TT></STRONG>\n        <DD>Applicable to MIP problems only. Set the method that will be\n        used to solve the problem at the nodes (except the root) of the \n        branch-and-bound tree. Note that the method for solving the root\n        node is controlled by the <TT>method</TT> option. Value can be set\n        to the same values as in the <TT>method</TT> option, although \n        there may be more restrictions on what the actual methods/auxiliary\n        methods that are allowed in combination with the root method,\n        due to limitations/restrictions from the external solver. A warning\n        will be given when the problem is solveed if this is the case, and \n        the default method used instead.\n\n<P>\n    <DT><STRONG><TT>solution</TT></STRONG>\n        <DD>Make the solutions available each time the problem has been\n        (re-)solved successfully.\n        Value is one of the atoms <TT>yes</TT> or <TT>no</TT>.\n\n<P>\n    <DT><STRONG><TT>reduced_cost</TT></STRONG>\n        <DD>Make the reduced costs available each time the problem has been\n        (re-)solved successfully. If the problem is a MIP, then depending on\n        the external solver, this is either unavailable or are the values for\n        the optimal LP node. \n        Value is one of the atoms <TT>yes</TT> or <TT>no</TT>.\n\n<P>\n    <DT><STRONG><TT>slack</TT></STRONG>\n        <DD>Make the constraint slacks available each time the problem has been\n        (re-)solved successfully.\n        Value is one of the atoms <TT>yes</TT> or <TT>no</TT>.\n\n<P>\n    <DT><STRONG><TT>dual_solution</TT></STRONG>\n       <DD>Make the dual solutions available each time the problem has been\n       (re-)solved successfully.  If the problem is a MIP, then depending on\n        the external solver, this is either unavailable or are the values for\n        the optimal LP node. \n        Value is one of the atoms <TT>yes</TT> or <TT>no</TT>.\n\n<P>\n    <DT><STRONG><TT>keep_basis</TT></STRONG>\n        <DD>Store the basis each time the problem has been solved successfully,\n        and use this basis as a starting point for re-solving next time.\n        Value is one of the atoms <TT>yes</TT> or <TT>no</TT>.\n\n<P>\n    <DT><STRONG><TT>demon_tolerance</TT></STRONG>\n        <DD>Specify how far outside a variable's range an lp-solution\n        can fall before lp_demon_setup/5 re-triggers.\n        Value is a comma-separated pair <TT>(RealTol,IntTol)</TT> of \n        floating-point values (default <TT>(0.00001,0.5)</TT>).\n\n<P>\n    <DT><STRONG><TT>use_var_names</TT></STRONG>\n        <DD>Specify if variable names (set using <TT>set_var_name/2</TT> of the\n        var_name library) should be passed to the external solver. If a\n        particular variable does not have a name, a solver's default name\n        would be used. Note that for XPRESS-MP, there is a limit on the\n        length of the name, which can be changed between 8 and 64 in steps\n        of 8 with the parameter <TT>N_NAMLEN</TT>. Variable names longer\n        than this limit are truncated to the limit. Note also that only \n        new variables from constraints added after the <TT>lp_set/3</TT> call \n        will pass their names to the external solver.\n        Value is one of the atoms <TT>yes</TT> or <TT>no</TT>.\n<P>\n    <DT><STRONG><TT>timeout</TT></STRONG>\n        <DD>Set the external solver to time-out after <TT>Value</TT>\n        seconds.  The solver will abort (in either the abort or suboptimal\n        state, depending on if a suboptimal solution was found) if the\n        optimal solution was not found within the time limit. In cases\n        where the solver expects an integer for the time-out interval, the\n        time given is rounded up to the next integer value. This should be\n        used instead of the solver specific optimizer_param(Param) for\n        setting timeouts.\n        Value is a positive number.\n<P>\n<DT><STRONG><TT>suboptimal_handler</TT></STRONG>\n        <DD>Value is a user defined goal to handle the case when the\n        external solver returned a suboptimal solution (because the problem\n        was aborted). Value would replace any existing suboptimal handler,\n        and would also be run in place of raising the default\n        <TT>eplex_suboptimal</TT> event.\n<P>\n<DT><STRONG><TT>unbounded_handler</TT></STRONG>\n        <DD>Value is a user defined goal to handle the case when the\n        problem is unbounded. Value would replace any existing unbounded\n        handler, and would be run in place of raising the default\n        <TT>eplex_unbounded</TT> event.\n<P>\n<DT><STRONG><TT>unknown_handler</TT></STRONG>\n        <DD>Value is a user defined goal to handle the case when the\n        external solver was not able to determine if the problem is\n        unbounded Value would replace any existing unknown handler, and\n        would be run in place of raising the default <TT>eplex_unknown</TT>\n        event.\n<P>\n<DT><STRONG><TT>abort_handler</TT></STRONG>\n        <DD>Value is a user defined goal to handle the case when the\n        external solver aborted without finding any solution.  Value would\n        replace any existing abort handler, and would be run in place of\n        raising the default <TT>eplex_abort</TT> event.\n<P>\n    <DT><STRONG><TT>optimizer_param(Param)</TT></STRONG>\n        <DD>Set the external solver's control parameter Param for the problem\n        <TT>Handle</TT>. If the solver's parameters are global and not\n        problem specific, an unimplemented functionality exception would\n        be raised. See lp_get/3 for more details on the external solver's\n        parameters. \n<P>\n    <DT><STRONG><TT>write_before_solve</TT></STRONG>\n       <DD>Value can be the pair (Format,File) or the atom no. If\n       (Format,File) is given, Eplex will ask the external solver to dump\n       the problem each time the solver is invoked by calling\n       <TT>lp_write/3</TT>. This allows the problem in an\n       <TT>eplex_probe/2</TT> or <TT>lp_probe/3</TT> to be\n       dumped. <TT>Format</TT> and <TT>File</TT> are simply passed to\n       <TT>lp_write/3</TT>. `no' will turn off this dumping.\n<P>\n    <DT><STRONG><TT>post_equality_when_unified</TT></STRONG>\n        <DD>Value can be the atoms yes or no. Determines if an equlity\n        constraint between two solver variables will be posted to the\n        solver when these variables are unified. Setting Value to no means\n        that the constraint will <EM>not</EM> be posted. Note that this can\n        lead to the solver's problem becoming inconsistent with\n        ECLiPSe's. \n<P>\n</DL>\n  Making solutions available means that they can be retrieved using\n  lp_get/3 or lp_var_get/4 after the solver has been run successfully.\n\n</P>")]).
:- comment(lp_setup / 4, [amode : lp_setup(+, +, ++, -), args : ["NormConstraints" : "normalised constraints", "Objective" : "Objective function: min(CostExpr) or max(CostExpr)", "ListOfOptions" : "List of solver options", "Handle" : "handle to solver state"], summary : "Create a new external solver state for the constraints NormConstraints.", see_also : [lp_add / 3, lp_set / 3, lp_add_vars / 2, lp_add_constraints / 3, lp_solve / 2, lp_probe / 3, lp_get / 3, normalise_cstrs / 3, lp_write / 3], desc : html("<P>\n    Create a new solver state for the set of constraints NormConstraints\n    (see normalise_cstrs/3 for how to obtain a set of normalised\n    constraints).  Apart from the explicitly listed constraints, the\n    variable's ranges will be taken into account as the variable bounds for\n    the simplex algorithm.  Undeclared variables are implicitly declared as\n    reals (see reals/1 of the range library).\n\n</P><P>\n    However, when variables have been declared integers (using ::/2 or\n    integers/1 of the range library) that is not taken into account by the\n    solver by default.  This means that the solver will only work on the\n    <EM>relaxed problem</EM> (ie. ignoring the integrality constraints),\n    unless specified otherwise in the options.\n\n</P><P>\n    CostExpr is a linear expression\n    (or quadratic if supported by the external solver).\n\n</P><P>\n    Options is a list of options (see below).\n\n\n</P><P>\n    A solver-handle Handle is returned which is used to refer to the solver\n    subsequently.\n\n</P><P>\n    Note: Some external solvers need to write temporary files when they\n    are solving a problem. These are written to the temporary directory\n    specified in ECLiPSe's tmp_dir setting (get_flag/2, set_flag/2).\n\n</P><P>\nThe solver Options are:\n<DL>\n\n<DT><STRONG><TT>integers(+ListOfVars)</TT></STRONG>\n    <DD>Consider the specified variables to be integers (whether or not\n    they have been declared such).\n    This option will instruct the external solver to use its own MIP solver\n    (ie. branch-and-bound search happens within the external solver) instead of\n    just the Simplex.\n\n<P>\n<DT><STRONG><TT>method(+Method)</TT></STRONG>\n    <DD>Use the specified method (<TT>default, primal, dual, net,\n    barrier, sifting</TT>) (representing Primal Simplex, Dual Simplex,\n    Network Simplex, Barrier, and Sifting respectively) to solve the\n    problem. For MIP problems, this specifies the start algorithm (the one\n    that is used to solve the initial relaxation). See the external\n    solver's manual for a description of these methods.\n<P> \n    For some of the methods, an additional `auxiliary' method may be \n    specified in brackets. These are:\n<DL>\n<P>\n      <DT><TT>net(Simplex)</TT>: \n      <DD>specifies the Simplex method (<TT>primal</TT> or <TT>dual</TT>) to \n      follow the network optimisation. For LP problems only.\n<P>\n      <DT><TT>barrier(Crossover)</TT>: \n      <DD>specifies how the crossover to a basic solution from the barrier\n      solution is performed. <TT>Crossover</TT> can be <TT>primal</TT>, \n      <TT>dual</TT>, or <TT>none</TT>. <TT>none</TT> means no crossover is\n      performed. \n<P>\n      <DT><TT>sifting(SubMethod)</TT>: \n      <DD>specifies the method for solving the sifting subproblem. \n      <TT>SubMethod</TT> can be <TT>primal, dual, net, barrier</TT>.\n<P>\n</DL>\n    For all the auxiliary methods, <TT>default</TT> can also be specified.\n    This is eqivalent to not specifying a auxiliary method at all. \n<P>\n    Note that not all the methods are available on all external solvers. \n    The default method would use the solver's default method to solve the\n    problem. The actual method depends on the external solver. If no method\n    is specified, default is used.\n\n<P>\n<DT><STRONG><TT>node_method(+Method)</TT></STRONG>\n    <DD>For MIP problems only. Use the specified method (<TT>default, primal,\n    dual, net, barrier, sifting</TT>) to solve the subproblem at each node\n    of the MIP search-tree, except the root node, which is specified by\n    <TT>method</TT> option above. See method option for more description of\n    the methods. Note that there are less choices in the specifications of\n    the auxiliary methods that in the method option, due to limitations in\n    the solvers. If a specified auxiliary method cannot be used, `default'\n    will be used instead.\n\n<P>\n<DT><STRONG><TT>solution(+YesNo)</TT></STRONG>\n    <DD>Make the solutions available each time the problem has been (re-)solved\n    successfully.\n    YesNo is one of the atoms <TT>yes</TT> or <TT>no</TT>, the default is \n    <TT>yes</TT>.\n\n<P>\n<DT><STRONG><TT>dual_solution(+YesNo)</TT></STRONG>\n    <DD>Make the dual solutions available each time the problem has been \n    (re-)solved successfully. If the problem is a MIP, then depending on\n    the external solver, this is either unavailable or are the values for\n    the optimal LP node. \n    YesNo is one of the atoms <TT>yes</TT> or <TT>no</TT>, the default is \n    <TT>no</TT>.\n\n<P>\n<DT><STRONG><TT>slack(+YesNo)</TT></STRONG>\n    <DD>Make the constraint slacks available each time the problem has been \n    (re-)solved successfully.\n    YesNo is one of the atoms <TT>yes</TT> or <TT>no</TT>, the default is \n    <TT>no</TT>.\n\n<P>\n<DT><STRONG><TT>reduced_cost(+YesNo)</TT></STRONG>\n    <DD>Make the reduced costs available each time the problem has been\n    (re-)solved successfully. If the problem is a MIP, then depending on\n    the external solver, this is either unavailable or are the values for\n    the optimal LP node. \n    YesNo is one of the atoms <TT>yes</TT> or <TT>no</TT>, the default is \n    <TT>no</TT>.\n\n<P>\n<DT><STRONG><TT>keep_basis(+YesNo)</TT></STRONG>\n    <DD>Store the basis each time the problem has been solved successfully,\n    and use this basis as a starting point for re-solving next time.\n    This option only affects performance.\n    YesNo is one of the atoms <TT>yes</TT> or <TT>no</TT>, the default is \n    <TT>no</TT>.\n\n<P>\n<DT><STRONG><TT>demon_tolerance(RealTol, IntTol)</TT></STRONG>\n    <DD>Specify how far outside a variable's range an lp-solution\n    can fall before lp_demon_setup/5 re-triggers.\n    <TT>RealTol</TT> and <TT>IntTol</TT> are floats and default to\n    0.00001 and 0.5 respectively.\n\n<P>\n<DT><STRONG><TT>sos1(VarList)</TT></STRONG>\n    <DD><TT>VarList</TT> is a list of variables which the solver should\n    treat as variables of a type 1 special ordered set (SOS), i.e. at most\n    one of the variables in the set can be non-zero.\n\n<P>\n<DT><STRONG><TT>sos2(VarList)</TT></STRONG>\n    <DD><TT>VarList</TT> is a list of variables which the solver should\n    treat as variables of a type 2 special ordered set (SOS), i.e. at most\n    two of the variables in the set can be non-zero.\n\n<P>\n<DT><STRONG><TT>presolve(+YesNo)</TT></STRONG>\n    <DD>Specify if the external solver should perform presolve for this\n    problem. With presolving, the external solver will transform the\n    problem before solving it. This can lead to significantly faster times\n    to find solutions. However, as the problem has been transformed, some\n    external solvers have restriction on accessing or changing the problem\n    state. In addition, if the solver is repeatedly called because the\n    problem is frequently modified, then presolve may not be an advantage.\n    YesNo is one of the atoms <TT>yes</TT> or <TT>no</TT>, the default is \n    determined by the global setting of <TT>presolve</TT>, which can be\n    changed via <TT>lp_set/2</TT>. The initial default is <TT>yes</TT>.\n    Note that the presolve setting cannot be changed for a problem once it\n    is set.\n<P>\n<DT><STRONG><TT>timeout(+TimeOut)</TT></STRONG>\n    <DD>Set the external solver to time-out after <TT>TimeOut</TT> seconds.\n    <TT>TimeOut</TT> is a positive number. The solver will abort (in either\n    the abort or suboptimal state, depending on if a suboptimal solution\n    was found) if the optimal solution was not found within the time\n    limit. This should be used instead of setting the solver-specific\n    parameter for time-out directly. In cases where the solver expects an\n    integer for the time-out interval, the time given is rounded up to the\n    next integer value.\n<P>\n<DT><STRONG><TT>suboptimal_handler(+Goal)</TT></STRONG>\n    <DD>Specifies a user defined goal Goal to handle the case when the\n    external solver returned a suboptimal solution (because the problem\n    was aborted). Goal would be run in place of raising the default \n    <TT>eplex_suboptimal</TT> event.\n<P>\n<DT><STRONG><TT>unbounded_handler(+Goal)</TT></STRONG>\n    <DD>Specifies a user defined goal Goal to handle the case when the\n    problem is unbounded. Goal would be run in place of raising the  \n    default <TT>eplex_unknown</TT> event.\n<P>\n<DT><STRONG><TT>unknown_handler(+Goal)</TT></STRONG>\n    <DD>Specifies a user defined goal Goal to handle the case when the\n    external solver was not able to determine if the problem is unbounded\n    or infeasible. Goal would be run in place of raising the default \n    <TT>eplex_unknown</TT> event.\n<P>\n<DT><STRONG><TT>abort_handler(+Goal)</TT></STRONG>\n    <DD>Specifies a user defined goal Goal to handle the case when the\n    external solver aborted without finding any solution. Goal would be \n    run in place of raising the default <TT>eplex_abort</TT> event.\n<P>\n<DT><STRONG><TT>use_var_names(+YesNo)</TT></STRONG>\n    <DD>Specify if variable names (set using <TT>set_var_name/2</TT> of the \n    var_name library) should be passed to the external solver. If a \n    particular variable does not have a name, a solver's default name \n    would be used. Note that for XPRESS-MP, there is a limit on the length\n    of the name, which can be changed between 8 and 64 in steps of 8 with\n    the parameter <TT>N_NAMLEN</TT>. Variable names longer than this limit \n    are truncated to the limit. \n    YesNo is one of the atoms <TT>yes</TT> or <TT>no</TT>, the default is \n    <TT>no</TT>.\n<P>\n    <DT><STRONG><TT>mip_use_copy(YesNo)</TT></STRONG>\n        <DD>Some external solvers do not allow a MIP problem to be modified\n        once the MIP search has been started. Eplex works around this\n        problem by making a copy of the problem and solving that, so that\n        the original problem can still be modified. This can be turned off to\n        avoid the overhead of making this copy, in which case the MIP\n        problem cannot be modified. This option is used only when solving a\n        MIP problem, and the external solver does not allow a MIP problem to\n        be modified; otherwise it is ignored.\n        YesNo is one of the atoms <TT>yes</TT> or <TT>no</TT>, the default \n        is <TT>yes</TT> so that the problem can be modified.\n<P>\n    <DT><STRONG><TT>write_before_solve(Format,File)</TT></STRONG>\n        <DD>This option is most useful for debugging purposes. If given,\n        Eplex will ask the external solver to dump the problem each time\n        the solver is invoked by calling <TT>lp_write/3</TT>. This allows\n        the problem in an <TT>eplex_probe/2</TT> or <TT>lp_probe/3</TT> to\n        be dumped. <TT>Format</TT> and <TT>File</TT> are simply passed to \n        <TT>lp_write/3</TT>.\n\n    <DT><STRONG><TT>post_equality_when_unified(+YesNo)</TT></STRONG>\n        <DD>This option determines if an equality constraint between two\n        variables will be posted to the solver when these variables are\n        unified. Setting <TT>YesNo</TT> to no means that the constraint \n        will <EM>not</EM> be posted. Note that this can lead to the\n        solver's problem becoming inconsistent with ECLiPSe's. \n<P>\n<DT><STRONG><TT>sync_bounds(+YesNo)</TT></STRONG>\n    <DD>This option determines if the bounds of the problems variables are\n    synchronised with other solvers (i.e. the generic bounds are obtained\n    with get_var_bounds/3 and then passed to the external solver) before\n    the external solver is invoked. This was always done for previous\n    non-standalone version of eplex. For standalone eplex, as the bounds\n    are communicated directly to the external solver, the synchronisation\n    of variable bounds is not needed unless the user is using eplex\n    co-operatively with other solvers (e.g. ic). Even in such cases, it may\n    be more efficient to communicate these bounds changes by explicitly\n    programming it, especially if the problem has many variables and bounds\n    changes happen only to a few of the variables. Setting <TT>YesNo</TT>\n    to yes should increase compatibility with previous code (but note that\n    previous eplex obtained the bounds from a specific bounds keeper like\n    ic or range rather than the generic bounds).  YesNo is one of the atoms\n    <TT>yes</TT> or <TT>no</TT>, the default is <TT>no</TT>.\n\n</DL>\n")]).
:- comment(lp_solve / 2, [amode : lp_solve(+, -), args : ["Handle" : "Handle to a solver state", "Cost" : "Value of returned solution"], summary : "Explicitly invoke the external solver.", fail_if : "External solver was unable to find a solution.", see_also : [lp_setup / 4, lp_add / 3, lp_get / 3, lp_var_get / 4], desc : html("<P>\n   A solver that was setup manually with lp_solve/2 needs to be \n   triggered explicitly using this predicate. \n</P><P>\n   The external solver's LP, QP or MIP solver is applied to the\n   problem represented by Handle.  Precisely which method is used\n   depends on the options given to lp_setup/4.  lp_solve/2 fails if\n   there is no solution or succeeds if an optimal solution is found,\n   returning the solution's cost in Cost (unlike with lp_demon_setup/5,\n   Cost gets instantiated to a number).  After a success, various\n   solution and status information can be retrieved using lp_get/3\n   and lp_var_get/4.\n</P><P>\n   When a solver is triggered repeatedly, each invocation will\n   automatically take into account the current variable bounds.  The set of\n   constraints considered by the solver is the one given when the solver\n   was created plus any new constraints that were added (lp_add/3) in the\n   meantime.\n</P><P>\n   The user can define their own handlers (per eplex instance/problem) to\n   handle cases where there was some  error condition, or some limits were \n   exceeded during the solving of the problem. If no handler was defined,\n   by default an event would be raised. These are:\n<DL>\n    <DT>suboptimal handler (eplex_suboptimal event)<DD>\n    \tThis means that a solution was found but it may be suboptimal.\n\tThe default behaviour is to print a warning and succeed.\n    <DT>unbounded_handler (eplex_unbounded event)<DD>\n\tThis means that the problem is unbounded.  The default\n\tbehaviour is to bind Cost to infinity (positive or negative\n\tdepending on the optimisation direction), print a warning and\n\tsucceed.  CAUTION: No solution values are computed when the\n\tproblem is unbounded, so unless the problem was set up with\n\tthe solution(no) option, an error will occur when trying to\n\tcontinue as if the optimisation had succeeded.\n    <DT>unknown_handler (eplex_unknown event)<DD>\n    \tThis means that due to the solution method chosen, it is unknown\n\twhether the problem is unbounded or infeasible. The default\n\tbehaviour is to print a warning and fail (even though this\n\tmay be logically wrong!).\n    <DT>abort_handler (eplex_abort event)<DD>\n    \tSome other error condition occurred during optimisation.\n\tThe default behaviour is to print an error and abort.\n</DL>\n</P>"), exceptions : [eplex_suboptimal : "Solution was found, but is possibly suboptimal", eplex_unbounded : "Problem is unbounded, no solution values", eplex_unknown : "Result is unknown (infeasible or unbounded)", eplex_abort : "External solver aborted for some reason"]]).
:- comment(lp_suspend_on_change / 3, [template : "EplexInstance:suspend_on_change(+Handle, ?Var, +Susp)", args : ["Handle" : "Handle to an eplex problem", "Var" : "A solver problem variable for solver associated with EplexInstance", "Susp" : "Suspension to schedule when the typed solution for this variable changes"], summary : "Record the given suspension to be scheduled whenever a solution is found for the Eplex handle."]).
:- comment(lp_var_get / 4, [amode : lp_var_get(+, +, ++, -), args : ["Handle" : "Handle to a solver state", "Var" : "A solver problem variable for Handle", "What" : "Specification for information wanted (atom)", "Value" : "Returned value of What"], summary : "Obtain information for an individual solver problem variable Var.", see_also : [eplex_var_get / 3], exceptions : [4 : "Handle is not instantiated.", 5 : "Handle is not a compound term.", 6 : "What is not a valid value.", 6 : "Var is not a problem variable for Handle.", 6 : "What is unavailable; the information was not requested at solver setup."], desc : html("<P>\n   Retrieve information about solver state and results related to a\n   particular variable or constraint, for the solver state represented by \n   Handle. Fails if no solution has been computed yet. What can take the \n   same values as those in eplex_var_get/3.")]).
:- comment(lp_var_get_bounds / 4, [amode : lp_var_get_bounds(+, ?, -, -), args : ["Handle" : "Handle to a solver state", "Var" : "A solver problem variable for Handle", "Lo" : "Lower bound for Var", "Hi" : "Upper bound for Var"], summary : "Returns the bounds stored in the solver state of Handle for Var.", resat : no, see_also : [eplex_var_get_bounds / 3, lp_var_set_bounds / 4], exceptions : [5 : "Handle is not in the form of a solver handle.", 6 : "Var is not a problem variable for Handle."], desc : html("\n    <P>\n    Returns the numeric bounds stored in the solver state of Handle for the\n    variable Var. The bounds are returned as floats. Var must be an\n    existing problem variable for Handle, i.e. it must occur in the \n    constraints posted to the solver state. ")]).
:- comment(lp_var_occurrence / 3, [amode : lp_var_occurrence(?, +, -), amode : lp_var_occurrence(?, -, -), args : ["Var" : "Variable", "Handle" : "Handle to a solver state, or a variable", "Index" : "Column number for Var in Handle's matrix (integer)"], summary : "Returns the column number Index for Var in the external solver represented by Handle", resat : "Yes (if Handle is a variable).", desc : html("\n    <P>\n    If Handle is a problem handle, then Index is the column number for the\n    variable Var in the problem matrix of the external solver presented by\n    Handle. If Handle is a variable, then the predicate returns the handles\n    and index for each problem handle the variable non-determinately. \n    </P>\n")]).
:- comment(lp_var_set_bounds / 4, [amode : lp_var_set_bounds(+, ?, +, +), args : ["Handle" : "Handle to a solver state", "Var" : "A solver problem variable for Handle", "Lo" : "New lower bound for Var (number)", "Hi" : "New upper bound for Var (number)"], summary : "Imposes new bounds for Var on the solver state of Handle.", resat : no, see_also : [lp_var_get_bounds / 4], fail_if : "Lo is greater than Hi.", exceptions : [5 : "Handle is not in the form of a solver handle.", 6 : "Var is not a problem variable for Handle."], desc : html("\n    <P>\n    Imposes numeric bounds on the solver state of Handle for the variable\n    Var. Each bound is only updated if it is more narrow than the current\n    bound for the variable. The bounds are converted to floats before they\n    are imposed, and no typing is implied by the type of the numbers. It is\n    possible to impose incompatible bounds for the same variable on\n    different solver states. Var must be an existing problem variable for\n    Handle, i.e. it must occur in the constraints posted to the solver\n    state. ")]).
:- comment(lp_write / 3, [amode : lp_write(+, ++, +), args : ["Handle" : "Handle to an existing solver state", "Format" : "lp or mps", "File" : "File name"], see_also : [lp_read / 3, lp_setup / 4], summary : "Write a solver problem to a file.", desc : html("\n   Write the problem which corresponds to Handle to a file. The set of\n   supported formats depends on the actual external solver which is used.\n   All solvers support the mps format. Some solvers on some operating\n   system platforms may change or append a suffix to the filename.\n   Note that the mps format does not specify the sense (min or max) of the\n   objective function.")]).
:- comment(normalise_cstrs / 3, [amode : normalise_cstrs(+, -, -), args : ["Constraints" : "List of arithmetic relations", "NormConstraints" : "Linear constraints from Constraints (normalised)", "NonlinConstraints" : "Non-linear constraints from Constraints"], summary : "Normalise the linear constraints in Constraints.", see_also : [$= / 2, $=< / 2, $>= / 2, (=:=) / 2, (=<) / 2, (>=) / 2], desc : html("  Constraints is a list of terms of the form X $= Y, X $>= Y or X $=< Y (or\n  their non-$ equivalents)  where X and Y are arithmetic expressions.  The linear\n  constraints are returned in normalised form in NormConstraints, the\n  nonlinear ones are returned unchanged in NonlinConstr.\n")]).
:- comment(piecewise_linear_hull / 3, [template : "EplexInstance:piecewise_linear_hull(?X, ++Points, ?Y)", args : ["X" : "Parameter/domain of the piecewise function", "Points" : "List of points defining the piecewise function", "Y" : "Result/range of piecewise the function"], summary : "Relates X and Y according to a piecewise linear function.", see_also : [_45931 : piecewise_linear / 3], desc : html("<P>\nThis predicate imposes the constraint Y = f(X), where f is a piecewise\nlinear function defined by Points.  Please see the documentation for\npiecewise_linear/3 for details of how the piecewise linear function is\nspecified.\n</P><P>\nThis predicate extends piecewise_linear/3 by also computing the convex hull\nof the portions of the constraint which are feasible with respect to the\ncurrent bounds (stored with the IC bounds) of X and Y.  Constraints (and\n bounds) defining this convex hull are then\npassed to the eplex solver.  These constraints are updated whenever new\nbounds on X or Y change the convex hull.\n</P><P>\nThis implementation of the piecewise\nconstraint accepts bounded reals in its arguments, but it\ndoes not fully support bounded reals of non-zero width (i.e.\nthose which do not correspond to a single floating point value).  As a\nresult, use of such bounded reals is not recommended at this time.</P>\n")]).
:- comment(reals / 1, [template : "EplexInstance:reals(?Vars)", args : ["Vars" : "Variable or number, or a list or submatrix of variables/numbers"], see_also : [_10486 : reals / 1, integers / 1, (::) / 2], summary : "Constraints Vars to the real domain for EplexInstance.", fail_if : "Vars contain elements which are neither variable or number.", desc : html("<P>\tConstrains Vars to the real domain in the eplex instance\n        EplexInstance. Any variables that are not problem variables\n        for EplexInstance are added to the problem, with unconstrained\n        bounds (except by the external solver's idea of infinity).\n</P><P>\n        Note that the notion of real is used here in the pure mathematical\n        sense, where real numbers subsume the integers. If the variables\n        are already instantiated, this call checks that the variable is\n        instantiated to a number.\n        ")]).
:- comment(reduced_cost_pruning / 2, [summary : "Prune bounds of all problem variables based on their reduced costs", amode : reduced_cost_pruning(+, ?), args : ["Handle" : "Handle to a (solved) solver state", "GlobalCost" : "Bounded global cost variable"], see_also : [lp_demon_setup / 5], fail_if : "None", desc : html("\n    <P>\n    Handle is a problem handle referring to the linear relaxation of\n    a more complex problem. GlobalCost is the overall cost variable\n    of the complex problem.\n    </P><P>\n    This predicate tries to prune the bounds of all variables that\n    occur in the linear relaxation, based on their reduced costs,\n    the optimum of the relaxation, and the currently known bounds\n    (lower if maximizing, upper if minimizing) on the global cost.\n    </P><P>\n    This predicate should be called just after the Handle has been solved.\n    In particular, it can be used as the post-goal in an lp-demon.\n    The solver should have been set up with the <TT>reduced_cost(yes)</TT>\n    option.\n    </P>\n")]).
:- comment(solution_out_of_range / 1, [amode : solution_out_of_range(+), args : ["Handle" : "Handle to a solver state"], see_also : [lp_demon_setup / 5], summary : "A trigger goal for lp_demon_setup/5.", desc : html("<P>\n  This is intended as a useful pre(Goal) for lp_demon_setup/5 in connection\n  with the <TT>bounds</TT> trigger mode.  It succeeds if any of the\n  solutions (computed by the most recent successful solving) of Handle are\n  more than a tolerance outside the range of the corresponding variables,\n  ie. couldn't be instantiated to this value.  The admissible tolerances\n  can be specified in lp_setup/4 or lp_set/3 as <TT>demon_tolerance</TT>.\n</P>")]).
:- comment(suspend_on_change / 2, [template : "EplexInstance:suspend_on_change(?Var, +Susp)", args : ["Var" : "A solver problem variable for solver associated with EplexInstance", "Susp" : "Suspension to schedule when the typed solution for this variable changes"], summary : "Record the given suspension to be scheduled whenever a solution is found for the EplexInstance."]).
:- comment(eplex_read_ / 3, hidden).
:- comment(eplex_solver_setup_ / 6, hidden).
:- comment(eplex_solver_setup_ / 5, hidden).
:- comment(eplex_solver_setup_ / 2, hidden).
